aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLi Jin <dragon-fly@qq.com>2022-08-19 18:05:31 +0800
committerLi Jin <dragon-fly@qq.com>2022-08-19 18:05:31 +0800
commit2ef8f936224fe8506673561d033142aeddcc44c1 (patch)
tree274c816874b28cf363d3aec0ef7c9a9b1a630c02
parenta4d4893c77f9c48dedc88472a2e418bfd65e33a1 (diff)
downloadyuescript-2ef8f936224fe8506673561d033142aeddcc44c1.tar.gz
yuescript-2ef8f936224fe8506673561d033142aeddcc44c1.tar.bz2
yuescript-2ef8f936224fe8506673561d033142aeddcc44c1.zip
fix format.
-rw-r--r--src/.clang-format17
-rw-r--r--src/yue.cpp62
-rw-r--r--src/yue_wasm.cpp12
-rw-r--r--src/yuescript/ast.cpp24
-rw-r--r--src/yuescript/ast.hpp138
-rw-r--r--src/yuescript/parser.cpp701
-rw-r--r--src/yuescript/parser.hpp140
-rwxr-xr-xsrc/yuescript/yue_ast.h28
-rwxr-xr-xsrc/yuescript/yue_compiler.cpp353
-rw-r--r--src/yuescript/yue_compiler.h9
-rwxr-xr-xsrc/yuescript/yue_parser.cpp48
-rwxr-xr-xsrc/yuescript/yue_parser.h18
-rw-r--r--src/yuescript/yuescript.cpp8
13 files changed, 737 insertions, 821 deletions
diff --git a/src/.clang-format b/src/.clang-format
new file mode 100644
index 0000000..5d305ae
--- /dev/null
+++ b/src/.clang-format
@@ -0,0 +1,17 @@
1# Format Style Options - Created with Clang Power Tools
2---
3BasedOnStyle: WebKit
4AllowShortCaseLabelsOnASingleLine: true
5AllowShortIfStatementsOnASingleLine: WithoutElse
6AllowShortLoopsOnASingleLine: true
7BreakBeforeBraces: Attach
8Cpp11BracedListStyle: true
9IndentCaseLabels: true
10NamespaceIndentation: None
11SpaceBeforeCpp11BracedList: false
12TabWidth: 4
13AlignEscapedNewlines: DontAlign
14AlwaysBreakBeforeMultilineStrings: true
15FixNamespaceComments: true
16UseTab: Always
17...
diff --git a/src/yue.cpp b/src/yue.cpp
index 6011d94..07d0fef 100644
--- a/src/yue.cpp
+++ b/src/yue.cpp
@@ -9,28 +9,28 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
9#include "yuescript/yue_compiler.h" 9#include "yuescript/yue_compiler.h"
10#include "yuescript/yue_parser.h" 10#include "yuescript/yue_parser.h"
11 11
12#include <iostream> 12#include <chrono>
13#include <iomanip>
14#include <cstdlib> 13#include <cstdlib>
15#include <limits>
16#include <fstream> 14#include <fstream>
17#include <chrono>
18#include <future> 15#include <future>
16#include <iomanip>
17#include <iostream>
18#include <limits>
19#include <memory>
19#include <sstream> 20#include <sstream>
20#include <tuple>
21#include <string_view> 21#include <string_view>
22#include <memory> 22#include <tuple>
23using namespace std::string_view_literals; 23using namespace std::string_view_literals;
24using namespace std::string_literals; 24using namespace std::string_literals;
25#include "ghc/fs_std.hpp" 25#include "ghc/fs_std.hpp"
26#include "linenoise.hpp" 26#include "linenoise.hpp"
27 27
28#if not (defined YUE_NO_MACRO && defined YUE_COMPILER_ONLY) 28#if not(defined YUE_NO_MACRO && defined YUE_COMPILER_ONLY)
29#define _DEFER(code,line) std::shared_ptr<void> _defer_##line(nullptr, [&](auto){code;}) 29#define _DEFER(code, line) std::shared_ptr<void> _defer_##line(nullptr, [&](auto) { code; })
30#define DEFER(code) _DEFER(code,__LINE__) 30#define DEFER(code) _DEFER(code, __LINE__)
31extern "C" { 31extern "C" {
32#include "lua.h"
33#include "lauxlib.h" 32#include "lauxlib.h"
33#include "lua.h"
34#include "lualib.h" 34#include "lualib.h"
35int luaopen_yue(lua_State* L); 35int luaopen_yue(lua_State* L);
36} // extern "C" 36} // extern "C"
@@ -81,7 +81,7 @@ void pushOptions(lua_State* L, int lineOffset) {
81#endif // not (defined YUE_NO_MACRO && defined YUE_COMPILER_ONLY) 81#endif // not (defined YUE_NO_MACRO && defined YUE_COMPILER_ONLY)
82 82
83#ifndef YUE_NO_MACRO 83#ifndef YUE_NO_MACRO
84#define YUE_ARGS nullptr,openlibs 84#define YUE_ARGS nullptr, openlibs
85#else 85#else
86#define YUE_ARGS 86#define YUE_ARGS
87#endif // YUE_NO_MACRO 87#endif // YUE_NO_MACRO
@@ -90,7 +90,7 @@ void pushOptions(lua_State* L, int lineOffset) {
90static const char luaminifyCodes[] = 90static const char luaminifyCodes[] =
91#include "LuaMinify.h" 91#include "LuaMinify.h"
92 92
93static void pushLuaminify(lua_State* L) { 93 static void pushLuaminify(lua_State * L) {
94 if (luaL_loadbuffer(L, luaminifyCodes, sizeof(luaminifyCodes) / sizeof(luaminifyCodes[0]) - 1, "=(luaminify)") != 0) { 94 if (luaL_loadbuffer(L, luaminifyCodes, sizeof(luaminifyCodes) / sizeof(luaminifyCodes[0]) - 1, "=(luaminify)") != 0) {
95 std::string err = "failed to load luaminify module.\n"s + lua_tostring(L, -1); 95 std::string err = "failed to load luaminify module.\n"s + lua_tostring(L, -1);
96 luaL_error(L, err.c_str()); 96 luaL_error(L, err.c_str());
@@ -103,27 +103,27 @@ static void pushLuaminify(lua_State* L) {
103 103
104int main(int narg, const char** args) { 104int main(int narg, const char** args) {
105 const char* help = 105 const char* help =
106"Usage: yue [options|files|directories] ...\n\n" 106 "Usage: yue [options|files|directories] ...\n\n"
107" -h Print this message\n" 107 " -h Print this message\n"
108#ifndef YUE_COMPILER_ONLY 108#ifndef YUE_COMPILER_ONLY
109" -e str Execute a file or raw codes\n" 109 " -e str Execute a file or raw codes\n"
110" -m Generate minified codes\n" 110 " -m Generate minified codes\n"
111#endif // YUE_COMPILER_ONLY 111#endif // YUE_COMPILER_ONLY
112" -t path Specify where to place compiled files\n" 112 " -t path Specify where to place compiled files\n"
113" -o file Write output to file\n" 113 " -o file Write output to file\n"
114" -s Use spaces in generated codes instead of tabs\n" 114 " -s Use spaces in generated codes instead of tabs\n"
115" -p Write output to standard out\n" 115 " -p Write output to standard out\n"
116" -b Dump compile time (doesn't write output)\n" 116 " -b Dump compile time (doesn't write output)\n"
117" -g Dump global variables used in NAME LINE COLUMN\n" 117 " -g Dump global variables used in NAME LINE COLUMN\n"
118" -l Write line numbers from source codes\n" 118 " -l Write line numbers from source codes\n"
119" -v Print version\n" 119 " -v Print version\n"
120#ifndef YUE_COMPILER_ONLY 120#ifndef YUE_COMPILER_ONLY
121" -- Read from standard in, print to standard out\n" 121 " -- Read from standard in, print to standard out\n"
122" (Must be first and only argument)\n\n" 122 " (Must be first and only argument)\n\n"
123" Execute without options to enter REPL, type symbol '$'\n" 123 " Execute without options to enter REPL, type symbol '$'\n"
124" in a single line to start/stop multi-line mode\n" 124 " in a single line to start/stop multi-line mode\n"
125#endif // YUE_COMPILER_ONLY 125#endif // YUE_COMPILER_ONLY
126; 126 ;
127#ifndef YUE_COMPILER_ONLY 127#ifndef YUE_COMPILER_ONLY
128 if (narg == 1) { 128 if (narg == 1) {
129 lua_State* L = luaL_newstate(); 129 lua_State* L = luaL_newstate();
@@ -276,7 +276,7 @@ int main(int narg, const char** args) {
276 std::string targetPath; 276 std::string targetPath;
277 std::string resultFile; 277 std::string resultFile;
278 std::string workPath; 278 std::string workPath;
279 std::list<std::pair<std::string,std::string>> files; 279 std::list<std::pair<std::string, std::string>> files;
280 for (int i = 1; i < narg; ++i) { 280 for (int i = 1; i < narg; ++i) {
281 std::string arg = args[i]; 281 std::string arg = args[i];
282 if (arg == "--"sv) { 282 if (arg == "--"sv) {
@@ -449,7 +449,7 @@ int main(int narg, const char** args) {
449 std::cout << "Error: -o can not be used with multiple input files\n"sv; 449 std::cout << "Error: -o can not be used with multiple input files\n"sv;
450 std::cout << help; 450 std::cout << help;
451 } 451 }
452 std::list<std::future<std::tuple<int,std::string,std::string>>> results; 452 std::list<std::future<std::tuple<int, std::string, std::string>>> results;
453 for (const auto& file : files) { 453 for (const auto& file : files) {
454 auto task = std::async(std::launch::async, [=]() { 454 auto task = std::async(std::launch::async, [=]() {
455 std::ifstream input(file.first, std::ios::in); 455 std::ifstream input(file.first, std::ios::in);
diff --git a/src/yue_wasm.cpp b/src/yue_wasm.cpp
index 8c93eb1..395388b 100644
--- a/src/yue_wasm.cpp
+++ b/src/yue_wasm.cpp
@@ -9,8 +9,8 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
9#include "yuescript/yue_compiler.h" 9#include "yuescript/yue_compiler.h"
10 10
11extern "C" { 11extern "C" {
12#include "lua.h"
13#include "lauxlib.h" 12#include "lauxlib.h"
13#include "lua.h"
14#include "lualib.h" 14#include "lualib.h"
15int luaopen_yue(lua_State* L); 15int luaopen_yue(lua_State* L);
16} // extern "C" 16} // extern "C"
@@ -23,15 +23,14 @@ static void openlibs(void* state) {
23 lua_pop(L, 1); 23 lua_pop(L, 1);
24} 24}
25 25
26#define YUE_ARGS nullptr,openlibs 26#define YUE_ARGS nullptr, openlibs
27 27
28#include <string_view> 28#include <string_view>
29using namespace std::string_view_literals; 29using namespace std::string_view_literals;
30#include <emscripten/bind.h> 30#include <emscripten/bind.h>
31using namespace emscripten; 31using namespace emscripten;
32 32
33struct YueResult 33struct YueResult {
34{
35 std::string codes; 34 std::string codes;
36 std::string err; 35 std::string err;
37}; 36};
@@ -47,8 +46,8 @@ YueResult tolua(const std::string& codes, bool reserveLineNumber = true, bool im
47 46
48std::string version() { return std::string(yue::version); } 47std::string version() { return std::string(yue::version); }
49 48
50#define _DEFER(code,line) std::shared_ptr<void> _defer_##line(nullptr, [&](auto){code;}) 49#define _DEFER(code, line) std::shared_ptr<void> _defer_##line(nullptr, [&](auto) { code; })
51#define DEFER(code) _DEFER(code,__LINE__) 50#define DEFER(code) _DEFER(code, __LINE__)
52 51
53void pushYue(lua_State* L, std::string_view name) { 52void pushYue(lua_State* L, std::string_view name) {
54 lua_getglobal(L, "package"); // package 53 lua_getglobal(L, "package"); // package
@@ -167,4 +166,3 @@ EMSCRIPTEN_BINDINGS(yue) {
167 function("exec", &exec); 166 function("exec", &exec);
168 function("version", &version); 167 function("version", &version);
169} 168}
170
diff --git a/src/yuescript/ast.cpp b/src/yuescript/ast.cpp
index 3deefb1..239aec6 100644
--- a/src/yuescript/ast.cpp
+++ b/src/yuescript/ast.cpp
@@ -13,11 +13,9 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
13 13
14#include "yuescript/ast.hpp" 14#include "yuescript/ast.hpp"
15 15
16
17namespace parserlib { 16namespace parserlib {
18 17
19 18traversal ast_node::traverse(const std::function<traversal(ast_node*)>& func) {
20traversal ast_node::traverse(const std::function<traversal (ast_node*)>& func) {
21 return func(this); 19 return func(this);
22} 20}
23 21
@@ -45,27 +43,25 @@ ast_node* ast_node::getByTypeIds(int* begin, int* end) {
45 return current; 43 return current;
46} 44}
47 45
48bool ast_node::visitChild(const std::function<bool (ast_node*)>&) { 46bool ast_node::visitChild(const std::function<bool(ast_node*)>&) {
49 return false; 47 return false;
50} 48}
51 49
52
53/** Asks all members to construct themselves from the stack. 50/** Asks all members to construct themselves from the stack.
54 The members are asked to construct themselves in reverse order. 51 The members are asked to construct themselves in reverse order.
55 from a node stack. 52 from a node stack.
56 @param st stack. 53 @param st stack.
57*/ 54*/
58void ast_container::construct(ast_stack &st) { 55void ast_container::construct(ast_stack& st) {
59 for(ast_member_vector::reverse_iterator it = m_members.rbegin(); 56 for (ast_member_vector::reverse_iterator it = m_members.rbegin();
60 it != m_members.rend(); 57 it != m_members.rend();
61 ++it) 58 ++it) {
62 {
63 ast_member* member = *it; 59 ast_member* member = *it;
64 member->construct(st); 60 member->construct(st);
65 } 61 }
66} 62}
67 63
68traversal ast_container::traverse(const std::function<traversal (ast_node*)>& func) { 64traversal ast_container::traverse(const std::function<traversal(ast_node*)>& func) {
69 traversal action = func(this); 65 traversal action = func(this);
70 switch (action) { 66 switch (action) {
71 case traversal::Stop: return traversal::Stop; 67 case traversal::Stop: return traversal::Stop;
@@ -96,7 +92,7 @@ traversal ast_container::traverse(const std::function<traversal (ast_node*)>& fu
96 return traversal::Continue; 92 return traversal::Continue;
97} 93}
98 94
99bool ast_container::visitChild(const std::function<bool (ast_node*)>& func) { 95bool ast_container::visitChild(const std::function<bool(ast_node*)>& func) {
100 const auto& members = this->members(); 96 const auto& members = this->members();
101 for (auto member : members) { 97 for (auto member : members) {
102 switch (member->get_type()) { 98 switch (member->get_type()) {
@@ -121,7 +117,6 @@ bool ast_container::visitChild(const std::function<bool (ast_node*)>& func) {
121 return false; 117 return false;
122} 118}
123 119
124
125/** parses the given input. 120/** parses the given input.
126 @param i input. 121 @param i input.
127 @param g root rule of grammar. 122 @param g root rule of grammar.
@@ -143,5 +138,4 @@ ast_node* parse(input& i, rule& g, error_list& el, void* ud) {
143 return st.front(); 138 return st.front();
144} 139}
145 140
146 141} // namespace parserlib
147} //namespace parserlib
diff --git a/src/yuescript/ast.hpp b/src/yuescript/ast.hpp
index 4860fc9..681c27f 100644
--- a/src/yuescript/ast.hpp
+++ b/src/yuescript/ast.hpp
@@ -11,40 +11,48 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
11 11
12#pragma once 12#pragma once
13 13
14
15#include <cassert> 14#include <cassert>
16#include <list> 15#include <list>
17#include <stdexcept> 16#include <stdexcept>
18#include <type_traits>
19#include <string_view> 17#include <string_view>
18#include <type_traits>
20 19
21#include "yuescript/parser.hpp" 20#include "yuescript/parser.hpp"
22 21
23
24namespace parserlib { 22namespace parserlib {
25 23
26
27class ast_node; 24class ast_node;
28template <bool Required, class T> class ast_ptr; 25template <bool Required, class T>
29template <bool Required, class T> class ast_list; 26class ast_ptr;
30template <class T> class ast; 27template <bool Required, class T>
31 28class ast_list;
29template <class T>
30class ast;
32 31
33/** type of AST node stack. 32/** type of AST node stack.
34*/ 33 */
35typedef std::vector<ast_node*> ast_stack; 34typedef std::vector<ast_node*> ast_stack;
36typedef std::list<ast_node*> node_container; 35typedef std::list<ast_node*> node_container;
37 36
38 37template <size_t Num>
39template<size_t Num> struct Counter { enum { value = Counter<Num-1>::value }; }; 38struct Counter {
40template<> struct Counter<0> { enum { value = 0 }; }; 39 enum { value = Counter<Num - 1>::value };
40};
41template <>
42struct Counter<0> {
43 enum { value = 0 };
44};
41 45
42#define COUNTER_READ Counter<__LINE__>::value 46#define COUNTER_READ Counter<__LINE__>::value
43#define COUNTER_INC template<> struct Counter<__LINE__> { enum { value = Counter<__LINE__-1>::value + 1}; } 47#define COUNTER_INC \
48 template <> \
49 struct Counter<__LINE__> { \
50 enum { value = Counter<__LINE__ - 1>::value + 1 }; \
51 }
44 52
45class ast_node; 53class ast_node;
46template<class T> 54template <class T>
47constexpr typename std::enable_if<std::is_base_of<ast_node,T>::value,int>::type 55constexpr typename std::enable_if<std::is_base_of<ast_node, T>::value, int>::type
48id(); 56id();
49 57
50enum class traversal { 58enum class traversal {
@@ -54,10 +62,11 @@ enum class traversal {
54}; 62};
55 63
56/** Base class for AST nodes. 64/** Base class for AST nodes.
57*/ 65 */
58class ast_node : public input_range { 66class ast_node : public input_range {
59public: 67public:
60 ast_node() : _ref(0) {} 68 ast_node()
69 : _ref(0) { }
61 70
62 void retain() { 71 void retain() {
63 ++_ref; 72 ++_ref;
@@ -74,32 +83,32 @@ public:
74 from a node stack. 83 from a node stack.
75 @param st stack. 84 @param st stack.
76 */ 85 */
77 virtual void construct(ast_stack&) {} 86 virtual void construct(ast_stack&) { }
78 87
79 /** interface for visiting AST tree use. 88 /** interface for visiting AST tree use.
80 */ 89 */
81 virtual traversal traverse(const std::function<traversal (ast_node*)>& func); 90 virtual traversal traverse(const std::function<traversal(ast_node*)>& func);
82 91
83 template <typename... Ts> 92 template <typename... Ts>
84 struct select_last { 93 struct select_last {
85 using type = typename decltype((std::enable_if<true,Ts>{}, ...))::type; 94 using type = typename decltype((std::enable_if<true, Ts>{}, ...))::type;
86 }; 95 };
87 template <typename... Ts> 96 template <typename... Ts>
88 using select_last_t = typename select_last<Ts...>::type; 97 using select_last_t = typename select_last<Ts...>::type;
89 98
90 template <class ...Args> 99 template <class... Args>
91 select_last_t<Args...>* getByPath() { 100 select_last_t<Args...>* getByPath() {
92 int types[] = {id<Args>()...}; 101 int types[] = {id<Args>()...};
93 return static_cast<select_last_t<Args...>*>(getByTypeIds(std::begin(types), std::end(types))); 102 return static_cast<select_last_t<Args...>*>(getByTypeIds(std::begin(types), std::end(types)));
94 } 103 }
95 104
96 virtual bool visitChild(const std::function<bool (ast_node*)>& func); 105 virtual bool visitChild(const std::function<bool(ast_node*)>& func);
97 106
98 virtual int getId() const = 0; 107 virtual int getId() const = 0;
99 108
100 virtual const std::string_view getName() const = 0; 109 virtual const std::string_view getName() const = 0;
101 110
102 template<class T> 111 template <class T>
103 inline ast_ptr<false, T> new_ptr() const { 112 inline ast_ptr<false, T> new_ptr() const {
104 auto item = new T; 113 auto item = new T;
105 item->m_begin.m_line = m_begin.m_line; 114 item->m_begin.m_line = m_begin.m_line;
@@ -108,27 +117,28 @@ public:
108 item->m_end.m_col = m_end.m_col; 117 item->m_end.m_col = m_end.m_col;
109 return ast_ptr<false, T>(item); 118 return ast_ptr<false, T>(item);
110 } 119 }
120
111private: 121private:
112 int _ref; 122 int _ref;
113 ast_node* getByTypeIds(int* begin, int* end); 123 ast_node* getByTypeIds(int* begin, int* end);
114}; 124};
115 125
116template<class T> 126template <class T>
117constexpr typename std::enable_if<std::is_base_of<ast_node,T>::value,int>::type 127constexpr typename std::enable_if<std::is_base_of<ast_node, T>::value, int>::type
118id() { return 0; } 128id() { return 0; }
119 129
120template<class T> 130template <class T>
121T* ast_cast(ast_node* node) { 131T* ast_cast(ast_node* node) {
122 return node && id<T>() == node->getId() ? static_cast<T*>(node) : nullptr; 132 return node && id<T>() == node->getId() ? static_cast<T*>(node) : nullptr;
123} 133}
124 134
125template<class T> 135template <class T>
126T* ast_to(ast_node* node) { 136T* ast_to(ast_node* node) {
127 assert(node->getId() == id<T>()); 137 assert(node->getId() == id<T>());
128 return static_cast<T*>(node); 138 return static_cast<T*>(node);
129} 139}
130 140
131template <class ...Args> 141template <class... Args>
132bool ast_is(ast_node* node) { 142bool ast_is(ast_node* node) {
133 if (!node) return false; 143 if (!node) return false;
134 bool result = false; 144 bool result = false;
@@ -141,12 +151,11 @@ bool ast_is(ast_node* node) {
141class ast_member; 151class ast_member;
142 152
143/** type of ast member vector. 153/** type of ast member vector.
144*/ 154 */
145typedef std::vector<ast_member*> ast_member_vector; 155typedef std::vector<ast_member*> ast_member_vector;
146 156
147
148/** base class for AST nodes with children. 157/** base class for AST nodes with children.
149*/ 158 */
150class ast_container : public ast_node { 159class ast_container : public ast_node {
151public: 160public:
152 void add_members(std::initializer_list<ast_member*> members) { 161 void add_members(std::initializer_list<ast_member*> members) {
@@ -169,9 +178,10 @@ public:
169 */ 178 */
170 virtual void construct(ast_stack& st) override; 179 virtual void construct(ast_stack& st) override;
171 180
172 virtual traversal traverse(const std::function<traversal (ast_node*)>& func) override; 181 virtual traversal traverse(const std::function<traversal(ast_node*)>& func) override;
182
183 virtual bool visitChild(const std::function<bool(ast_node*)>& func) override;
173 184
174 virtual bool visitChild(const std::function<bool (ast_node*)>& func) override;
175private: 185private:
176 ast_member_vector m_members; 186 ast_member_vector m_members;
177 187
@@ -184,10 +194,10 @@ enum class ast_holder_type {
184}; 194};
185 195
186/** Base class for children of ast_container. 196/** Base class for children of ast_container.
187*/ 197 */
188class ast_member { 198class ast_member {
189public: 199public:
190 virtual ~ast_member() {} 200 virtual ~ast_member() { }
191 201
192 /** interface for filling the the member from a node stack. 202 /** interface for filling the the member from a node stack.
193 @param st stack. 203 @param st stack.
@@ -199,10 +209,10 @@ public:
199 virtual ast_holder_type get_type() const = 0; 209 virtual ast_holder_type get_type() const = 0;
200}; 210};
201 211
202
203class _ast_ptr : public ast_member { 212class _ast_ptr : public ast_member {
204public: 213public:
205 _ast_ptr(ast_node* node) : m_ptr(node) { 214 _ast_ptr(ast_node* node)
215 : m_ptr(node) {
206 if (node) node->retain(); 216 if (node) node->retain();
207 } 217 }
208 218
@@ -250,6 +260,7 @@ public:
250 virtual ast_holder_type get_type() const override { 260 virtual ast_holder_type get_type() const override {
251 return ast_holder_type::Pointer; 261 return ast_holder_type::Pointer;
252 } 262 }
263
253protected: 264protected:
254 ast_node* m_ptr; 265 ast_node* m_ptr;
255}; 266};
@@ -260,11 +271,14 @@ protected:
260 @tparam Required if true, the object is required. 271 @tparam Required if true, the object is required.
261 @tparam T type of object to control. 272 @tparam T type of object to control.
262*/ 273*/
263template <bool Required, class T> class ast_ptr : public _ast_ptr { 274template <bool Required, class T>
275class ast_ptr : public _ast_ptr {
264public: 276public:
265 ast_ptr(T* node = nullptr) : _ast_ptr(node) {} 277 ast_ptr(T* node = nullptr)
278 : _ast_ptr(node) { }
266 279
267 ast_ptr(const ast_ptr& other) : _ast_ptr(other.get()) {} 280 ast_ptr(const ast_ptr& other)
281 : _ast_ptr(other.get()) { }
268 282
269 ast_ptr& operator=(const ast_ptr& other) { 283 ast_ptr& operator=(const ast_ptr& other) {
270 set(other.get()); 284 set(other.get());
@@ -315,17 +329,21 @@ public:
315 m_ptr = node; 329 m_ptr = node;
316 node->retain(); 330 node->retain();
317 } 331 }
332
318private: 333private:
319 virtual bool accept(ast_node* node) override { 334 virtual bool accept(ast_node* node) override {
320 return node && (std::is_same<ast_node,T>() || id<T>() == node->getId()); 335 return node && (std::is_same<ast_node, T>() || id<T>() == node->getId());
321 } 336 }
322}; 337};
323 338
324template <bool Required, class ...Args> class ast_sel : public _ast_ptr { 339template <bool Required, class... Args>
340class ast_sel : public _ast_ptr {
325public: 341public:
326 ast_sel() : _ast_ptr(nullptr) {} 342 ast_sel()
343 : _ast_ptr(nullptr) { }
327 344
328 ast_sel(const ast_sel& other) : _ast_ptr(other.get()) {} 345 ast_sel(const ast_sel& other)
346 : _ast_ptr(other.get()) { }
329 347
330 ast_sel& operator=(const ast_sel& other) { 348 ast_sel& operator=(const ast_sel& other) {
331 set(other.get()); 349 set(other.get());
@@ -355,6 +373,7 @@ public:
355 m_ptr = node; 373 m_ptr = node;
356 node->retain(); 374 node->retain();
357 } 375 }
376
358private: 377private:
359 virtual bool accept(ast_node* node) override { 378 virtual bool accept(ast_node* node) override {
360 if (!node) return false; 379 if (!node) return false;
@@ -428,14 +447,14 @@ public:
428 } 447 }
429 448
430 void clear() { 449 void clear() {
431 for(ast_node* obj : m_objects) { 450 for (ast_node* obj : m_objects) {
432 if (obj) obj->release(); 451 if (obj) obj->release();
433 } 452 }
434 m_objects.clear(); 453 m_objects.clear();
435 } 454 }
436 455
437 void dup(const _ast_list& src) { 456 void dup(const _ast_list& src) {
438 for(ast_node* obj : src.m_objects) { 457 for (ast_node* obj : src.m_objects) {
439 m_objects.push_back(obj); 458 m_objects.push_back(obj);
440 obj->retain(); 459 obj->retain();
441 } 460 }
@@ -444,6 +463,7 @@ public:
444 virtual ast_holder_type get_type() const override { 463 virtual ast_holder_type get_type() const override {
445 return ast_holder_type::List; 464 return ast_holder_type::List;
446 } 465 }
466
447protected: 467protected:
448 node_container m_objects; 468 node_container m_objects;
449}; 469};
@@ -454,7 +474,8 @@ protected:
454 @tparam Required if true, the object is required. 474 @tparam Required if true, the object is required.
455 @tparam T type of object to control. 475 @tparam T type of object to control.
456*/ 476*/
457template <bool Required, class T> class ast_list : public _ast_list { 477template <bool Required, class T>
478class ast_list : public _ast_list {
458public: 479public:
459 ast_list() { } 480 ast_list() { }
460 481
@@ -471,7 +492,7 @@ public:
471 /** Pops objects of type T from the stack until no more objects can be popped. 492 /** Pops objects of type T from the stack until no more objects can be popped.
472 @param st stack. 493 @param st stack.
473 */ 494 */
474 virtual void construct(ast_stack &st) override { 495 virtual void construct(ast_stack& st) override {
475 while (!st.empty()) { 496 while (!st.empty()) {
476 ast_node* node = st.back(); 497 ast_node* node = st.back();
477 // if the object was not not of the appropriate type, 498 // if the object was not not of the appropriate type,
@@ -491,13 +512,15 @@ public:
491 throw std::logic_error("Invalid AST stack."); 512 throw std::logic_error("Invalid AST stack.");
492 } 513 }
493 } 514 }
515
494private: 516private:
495 virtual bool accept(ast_node* node) override { 517 virtual bool accept(ast_node* node) override {
496 return node && (std::is_same<ast_node,T>() || id<T>() == node->getId()); 518 return node && (std::is_same<ast_node, T>() || id<T>() == node->getId());
497 } 519 }
498}; 520};
499 521
500template <bool Required, class ...Args> class ast_sel_list : public _ast_list { 522template <bool Required, class... Args>
523class ast_sel_list : public _ast_list {
501public: 524public:
502 ast_sel_list() { } 525 ast_sel_list() { }
503 526
@@ -511,7 +534,7 @@ public:
511 return *this; 534 return *this;
512 } 535 }
513 536
514 virtual void construct(ast_stack &st) override { 537 virtual void construct(ast_stack& st) override {
515 while (!st.empty()) { 538 while (!st.empty()) {
516 ast_node* node = st.back(); 539 ast_node* node = st.back();
517 if (!ast_sel_list::accept(node)) { 540 if (!ast_sel_list::accept(node)) {
@@ -528,6 +551,7 @@ public:
528 throw std::logic_error("Invalid AST stack."); 551 throw std::logic_error("Invalid AST stack.");
529 } 552 }
530 } 553 }
554
531private: 555private:
532 virtual bool accept(ast_node* node) override { 556 virtual bool accept(ast_node* node) override {
533 if (!node) return false; 557 if (!node) return false;
@@ -541,7 +565,8 @@ private:
541/** AST function which creates an object of type T 565/** AST function which creates an object of type T
542 and pushes it to the node stack. 566 and pushes it to the node stack.
543*/ 567*/
544template <class T> class ast { 568template <class T>
569class ast {
545public: 570public:
546 /** constructor. 571 /** constructor.
547 @param r rule to attach the AST function to. 572 @param r rule to attach the AST function to.
@@ -549,8 +574,9 @@ public:
549 ast(rule& r) { 574 ast(rule& r) {
550 r.set_parse_proc(&_parse_proc); 575 r.set_parse_proc(&_parse_proc);
551 } 576 }
577
552private: 578private:
553 //parse proc 579 // parse proc
554 static void _parse_proc(const pos& b, const pos& e, void* d) { 580 static void _parse_proc(const pos& b, const pos& e, void* d) {
555 ast_stack* st = reinterpret_cast<ast_stack*>(d); 581 ast_stack* st = reinterpret_cast<ast_stack*>(d);
556 T* obj = new T; 582 T* obj = new T;
@@ -561,7 +587,6 @@ private:
561 } 587 }
562}; 588};
563 589
564
565/** parses the given input. 590/** parses the given input.
566 @param i input. 591 @param i input.
567 @param g root rule of grammar. 592 @param g root rule of grammar.
@@ -572,5 +597,4 @@ private:
572*/ 597*/
573ast_node* parse(input& i, rule& g, error_list& el, void* ud); 598ast_node* parse(input& i, rule& g, error_list& el, void* ud);
574 599
575 600} // namespace parserlib
576} //namespace parserlib
diff --git a/src/yuescript/parser.cpp b/src/yuescript/parser.cpp
index a44ae34..a6eb513 100644
--- a/src/yuescript/parser.cpp
+++ b/src/yuescript/parser.cpp
@@ -9,222 +9,210 @@ Redistributions in binary form must reproduce the above copyright notice, this l
9 9
10THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.*/ 10THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.*/
11 11
12#include <cassert>
12#include <cstdlib> 13#include <cstdlib>
13#include <cstring> 14#include <cstring>
14#include <cassert>
15#include <stdexcept> 15#include <stdexcept>
16#include <unordered_map> 16#include <unordered_map>
17#include <unordered_set> 17#include <unordered_set>
18 18
19#include "yuescript/parser.hpp" 19#include "yuescript/parser.hpp"
20 20
21
22namespace parserlib { 21namespace parserlib {
23 22
24 23// internal private class that manages access to the public classes' internals.
25//internal private class that manages access to the public classes' internals.
26class _private { 24class _private {
27public: 25public:
28 //get the internal expression object from the expression. 26 // get the internal expression object from the expression.
29 static _expr* get_expr(const expr& e) { 27 static _expr* get_expr(const expr& e) {
30 return e.m_expr; 28 return e.m_expr;
31 } 29 }
32 30
33 //create new expression from given expression 31 // create new expression from given expression
34 static expr construct_expr(_expr* e) { 32 static expr construct_expr(_expr* e) {
35 return e; 33 return e;
36 } 34 }
37 35
38 //get the internal expression object from the rule. 36 // get the internal expression object from the rule.
39 static _expr* get_expr(rule& r) { 37 static _expr* get_expr(rule& r) {
40 return r.m_expr; 38 return r.m_expr;
41 } 39 }
42 40
43 //get the internal parse proc from the rule. 41 // get the internal parse proc from the rule.
44 static parse_proc get_parse_proc(rule& r) { 42 static parse_proc get_parse_proc(rule& r) {
45 return r.m_parse_proc; 43 return r.m_parse_proc;
46 } 44 }
47}; 45};
48 46
49
50class _context; 47class _context;
51 48
52 49// parser state
53//parser state
54class _state { 50class _state {
55public: 51public:
56 //position 52 // position
57 pos m_pos; 53 pos m_pos;
58 54
59 //size of match vector 55 // size of match vector
60 size_t m_matches; 56 size_t m_matches;
61 57
62 //constructor 58 // constructor
63 _state(_context& con); 59 _state(_context& con);
64}; 60};
65 61
66 62// match
67//match
68class _match { 63class _match {
69public: 64public:
70 //rule matched 65 // rule matched
71 rule* m_rule; 66 rule* m_rule;
72 67
73 //begin position 68 // begin position
74 pos m_begin; 69 pos m_begin;
75 70
76 //end position 71 // end position
77 pos m_end; 72 pos m_end;
78 73
79 //null constructor 74 // null constructor
80 _match() {} 75 _match() { }
81 76
82 //constructor from parameters 77 // constructor from parameters
83 _match(rule* r, const pos& b, const pos& e) : 78 _match(rule* r, const pos& b, const pos& e)
84 m_rule(r), 79 : m_rule(r)
85 m_begin(b), 80 , m_begin(b)
86 m_end(e) 81 , m_end(e) {
87 {
88 } 82 }
89}; 83};
90 84
91 85// match vector
92//match vector
93typedef std::vector<_match> _match_vector; 86typedef std::vector<_match> _match_vector;
94 87
95 88// parsing context
96//parsing context
97class _context { 89class _context {
98public: 90public:
99 //user data 91 // user data
100 void* m_user_data; 92 void* m_user_data;
101 93
102 //current position 94 // current position
103 pos m_pos; 95 pos m_pos;
104 96
105 //error position 97 // error position
106 pos m_error_pos; 98 pos m_error_pos;
107 99
108 //input begin 100 // input begin
109 input::iterator m_begin; 101 input::iterator m_begin;
110 102
111 //input end 103 // input end
112 input::iterator m_end; 104 input::iterator m_end;
113 105
114 //matches 106 // matches
115 _match_vector m_matches; 107 _match_vector m_matches;
116 108
117 //constructor 109 // constructor
118 _context(input& i, void* ud) : 110 _context(input& i, void* ud)
119 m_user_data(ud), 111 : m_user_data(ud)
120 m_pos(i), 112 , m_pos(i)
121 m_error_pos(i), 113 , m_error_pos(i)
122 m_begin(i.begin()), 114 , m_begin(i.begin())
123 m_end(i.end()) 115 , m_end(i.end()) {
124 {
125 } 116 }
126 117
127 //check if the end is reached 118 // check if the end is reached
128 bool end() const { 119 bool end() const {
129 return m_pos.m_it == m_end; 120 return m_pos.m_it == m_end;
130 } 121 }
131 122
132 //get the current symbol 123 // get the current symbol
133 input::value_type symbol() const { 124 input::value_type symbol() const {
134 assert(!end()); 125 assert(!end());
135 return *m_pos.m_it; 126 return *m_pos.m_it;
136 } 127 }
137 128
138 //set the longest possible error 129 // set the longest possible error
139 void set_error_pos() { 130 void set_error_pos() {
140 if (m_pos.m_it > m_error_pos.m_it) { 131 if (m_pos.m_it > m_error_pos.m_it) {
141 m_error_pos = m_pos; 132 m_error_pos = m_pos;
142 } 133 }
143 } 134 }
144 135
145 //next column 136 // next column
146 void next_col() { 137 void next_col() {
147 ++m_pos.m_it; 138 ++m_pos.m_it;
148 ++m_pos.m_col; 139 ++m_pos.m_col;
149 } 140 }
150 141
151 //next line 142 // next line
152 void next_line() { 143 void next_line() {
153 ++m_pos.m_line; 144 ++m_pos.m_line;
154 m_pos.m_col = 1; 145 m_pos.m_col = 1;
155 } 146 }
156 147
157 //restore the state 148 // restore the state
158 void restore(const _state& st) { 149 void restore(const _state& st) {
159 m_pos = st.m_pos; 150 m_pos = st.m_pos;
160 m_matches.resize(st.m_matches); 151 m_matches.resize(st.m_matches);
161 } 152 }
162 153
163 //parse non-term rule. 154 // parse non-term rule.
164 bool parse_non_term(rule& r); 155 bool parse_non_term(rule& r);
165 156
166 //parse term rule. 157 // parse term rule.
167 bool parse_term(rule& r); 158 bool parse_term(rule& r);
168 159
169 //execute all the parse procs 160 // execute all the parse procs
170 void do_parse_procs(void* d) const { 161 void do_parse_procs(void* d) const {
171 for(_match_vector::const_iterator it = m_matches.begin(); 162 for (_match_vector::const_iterator it = m_matches.begin();
172 it != m_matches.end(); 163 it != m_matches.end();
173 ++it) { 164 ++it) {
174 const _match &m = *it; 165 const _match& m = *it;
175 parse_proc p = _private::get_parse_proc(*m.m_rule); 166 parse_proc p = _private::get_parse_proc(*m.m_rule);
176 p(m.m_begin, m.m_end, d); 167 p(m.m_begin, m.m_end, d);
177 } 168 }
178 } 169 }
179 170
180private: 171private:
181 //parse non-term rule. 172 // parse non-term rule.
182 bool _parse_non_term(rule& r); 173 bool _parse_non_term(rule& r);
183 174
184 //parse term rule. 175 // parse term rule.
185 bool _parse_term(rule& r); 176 bool _parse_term(rule& r);
186}; 177};
187 178
188 179// base class for expressions
189//base class for expressions
190class _expr { 180class _expr {
191public: 181public:
192 //destructor. 182 // destructor.
193 virtual ~_expr() { 183 virtual ~_expr() {
194 } 184 }
195 185
196 //parse with whitespace 186 // parse with whitespace
197 virtual bool parse_non_term(_context& con) const = 0; 187 virtual bool parse_non_term(_context& con) const = 0;
198 188
199 //parse terminal 189 // parse terminal
200 virtual bool parse_term(_context& con) const = 0; 190 virtual bool parse_term(_context& con) const = 0;
201}; 191};
202 192
203 193// single character expression.
204//single character expression.
205class _char : public _expr { 194class _char : public _expr {
206public: 195public:
207 //constructor. 196 // constructor.
208 _char(char c) : 197 _char(char c)
209 m_char(c) 198 : m_char(c) {
210 {
211 } 199 }
212 200
213 //parse with whitespace 201 // parse with whitespace
214 virtual bool parse_non_term(_context& con) const { 202 virtual bool parse_non_term(_context& con) const {
215 return _parse(con); 203 return _parse(con);
216 } 204 }
217 205
218 //parse terminal 206 // parse terminal
219 virtual bool parse_term(_context& con) const { 207 virtual bool parse_term(_context& con) const {
220 return _parse(con); 208 return _parse(con);
221 } 209 }
222 210
223private: 211private:
224 //character 212 // character
225 input::value_type m_char; 213 input::value_type m_char;
226 214
227 //internal parse 215 // internal parse
228 bool _parse(_context& con) const { 216 bool _parse(_context& con) const {
229 if (!con.end()) { 217 if (!con.end()) {
230 input::value_type ch = con.symbol(); 218 input::value_type ch = con.symbol();
@@ -238,34 +226,33 @@ private:
238 } 226 }
239}; 227};
240 228
241 229// string expression.
242//string expression.
243class _string : public _expr { 230class _string : public _expr {
244public: 231public:
245 //constructor from ansi string. 232 // constructor from ansi string.
246 _string(const char* s) : 233 _string(const char* s)
247 m_string(Converter{}.from_bytes(s)) 234 : m_string(Converter{}.from_bytes(s)) {
248 {
249 } 235 }
250 236
251 //parse with whitespace 237 // parse with whitespace
252 virtual bool parse_non_term(_context& con) const { 238 virtual bool parse_non_term(_context& con) const {
253 return _parse(con); 239 return _parse(con);
254 } 240 }
255 241
256 //parse terminal 242 // parse terminal
257 virtual bool parse_term(_context& con) const { 243 virtual bool parse_term(_context& con) const {
258 return _parse(con); 244 return _parse(con);
259 } 245 }
260 246
261private: 247private:
262 //string 248 // string
263 input m_string; 249 input m_string;
264 250
265 //parse the string 251 // parse the string
266 bool _parse(_context& con) const { 252 bool _parse(_context& con) const {
267 for(input::const_iterator it = m_string.begin(), 253 for (input::const_iterator it = m_string.begin(),
268 end = m_string.end();;) { 254 end = m_string.end();
255 ;) {
269 if (it == end) return true; 256 if (it == end) return true;
270 if (con.end()) break; 257 if (con.end()) break;
271 if (con.symbol() != *it) break; 258 if (con.symbol() != *it) break;
@@ -277,44 +264,43 @@ private:
277 } 264 }
278}; 265};
279 266
280 267// set expression.
281//set expression.
282class _set : public _expr { 268class _set : public _expr {
283public: 269public:
284 //constructor from ansi string. 270 // constructor from ansi string.
285 _set(const char* s) { 271 _set(const char* s) {
286 auto str = Converter{}.from_bytes(s); 272 auto str = Converter{}.from_bytes(s);
287 for (auto ch : str) { 273 for (auto ch : str) {
288 _add(ch); 274 _add(ch);
289 } 275 }
290 } 276 }
291 277
292 //constructor from range. 278 // constructor from range.
293 _set(int min, int max) { 279 _set(int min, int max) {
294 assert(min >= 0); 280 assert(min >= 0);
295 assert(min <= max); 281 assert(min <= max);
296 m_quick_set.resize((size_t)max + 1U); 282 m_quick_set.resize((size_t)max + 1U);
297 for(; min <= max; ++min) { 283 for (; min <= max; ++min) {
298 m_quick_set[(size_t)min] = true; 284 m_quick_set[(size_t)min] = true;
299 } 285 }
300 } 286 }
301 287
302 //parse with whitespace 288 // parse with whitespace
303 virtual bool parse_non_term(_context& con) const { 289 virtual bool parse_non_term(_context& con) const {
304 return _parse(con); 290 return _parse(con);
305 } 291 }
306 292
307 //parse terminal 293 // parse terminal
308 virtual bool parse_term(_context& con) const { 294 virtual bool parse_term(_context& con) const {
309 return _parse(con); 295 return _parse(con);
310 } 296 }
311 297
312private: 298private:
313 //set is kept as an array of flags, for quick access 299 // set is kept as an array of flags, for quick access
314 std::vector<bool> m_quick_set; 300 std::vector<bool> m_quick_set;
315 std::unordered_set<size_t> m_large_set; 301 std::unordered_set<size_t> m_large_set;
316 302
317 //add character 303 // add character
318 void _add(size_t i) { 304 void _add(size_t i) {
319 if (i <= m_quick_set.size() || i <= 255) { 305 if (i <= m_quick_set.size() || i <= 255) {
320 if (i >= m_quick_set.size()) { 306 if (i >= m_quick_set.size()) {
@@ -326,7 +312,7 @@ private:
326 } 312 }
327 } 313 }
328 314
329 //internal parse 315 // internal parse
330 bool _parse(_context& con) const { 316 bool _parse(_context& con) const {
331 if (!con.end()) { 317 if (!con.end()) {
332 size_t ch = con.symbol(); 318 size_t ch = con.symbol();
@@ -345,59 +331,53 @@ private:
345 } 331 }
346}; 332};
347 333
348 334// base class for unary expressions
349//base class for unary expressions
350class _unary : public _expr { 335class _unary : public _expr {
351public: 336public:
352 //constructor. 337 // constructor.
353 _unary(_expr* e) : 338 _unary(_expr* e)
354 m_expr(e) 339 : m_expr(e) {
355 {
356 } 340 }
357 341
358 //destructor. 342 // destructor.
359 virtual ~_unary() { 343 virtual ~_unary() {
360 delete m_expr; 344 delete m_expr;
361 } 345 }
362 346
363protected: 347protected:
364 //expression 348 // expression
365 _expr *m_expr; 349 _expr* m_expr;
366}; 350};
367 351
368 352// terminal
369//terminal
370class _term : public _unary { 353class _term : public _unary {
371public: 354public:
372 //constructor. 355 // constructor.
373 _term(_expr* e) : 356 _term(_expr* e)
374 _unary(e) 357 : _unary(e) {
375 {
376 } 358 }
377 359
378 //parse with whitespace 360 // parse with whitespace
379 virtual bool parse_non_term(_context& con) const { 361 virtual bool parse_non_term(_context& con) const {
380 return m_expr->parse_term(con); 362 return m_expr->parse_term(con);
381 } 363 }
382 364
383 //parse terminal 365 // parse terminal
384 virtual bool parse_term(_context& con) const { 366 virtual bool parse_term(_context& con) const {
385 return m_expr->parse_term(con); 367 return m_expr->parse_term(con);
386 } 368 }
387}; 369};
388 370
389 371// user
390//user
391class _user : public _unary { 372class _user : public _unary {
392public: 373public:
393 //constructor. 374 // constructor.
394 _user(_expr* e, const user_handler& callback) : 375 _user(_expr* e, const user_handler& callback)
395 _unary(e), 376 : _unary(e)
396 m_handler(callback) 377 , m_handler(callback) {
397 {
398 } 378 }
399 379
400 //parse with whitespace 380 // parse with whitespace
401 virtual bool parse_non_term(_context& con) const { 381 virtual bool parse_non_term(_context& con) const {
402 pos pos = con.m_pos; 382 pos pos = con.m_pos;
403 if (m_expr->parse_non_term(con)) { 383 if (m_expr->parse_non_term(con)) {
@@ -407,7 +387,7 @@ public:
407 return false; 387 return false;
408 } 388 }
409 389
410 //parse terminal 390 // parse terminal
411 virtual bool parse_term(_context& con) const { 391 virtual bool parse_term(_context& con) const {
412 pos pos = con.m_pos; 392 pos pos = con.m_pos;
413 if (m_expr->parse_term(con)) { 393 if (m_expr->parse_term(con)) {
@@ -416,31 +396,30 @@ public:
416 } 396 }
417 return false; 397 return false;
418 } 398 }
399
419private: 400private:
420 user_handler m_handler; 401 user_handler m_handler;
421}; 402};
422 403
423 404// loop 0
424//loop 0
425class _loop0 : public _unary { 405class _loop0 : public _unary {
426public: 406public:
427 //constructor. 407 // constructor.
428 _loop0(_expr* e) : 408 _loop0(_expr* e)
429 _unary(e) 409 : _unary(e) {
430 {
431 } 410 }
432 411
433 //parse with whitespace 412 // parse with whitespace
434 virtual bool parse_non_term(_context& con) const { 413 virtual bool parse_non_term(_context& con) const {
435 //if parsing of the first fails, restore the context and stop 414 // if parsing of the first fails, restore the context and stop
436 _state st(con); 415 _state st(con);
437 if (!m_expr->parse_non_term(con)) { 416 if (!m_expr->parse_non_term(con)) {
438 con.restore(st); 417 con.restore(st);
439 return true; 418 return true;
440 } 419 }
441 420
442 //parse the rest 421 // parse the rest
443 for(;;) { 422 for (;;) {
444 _state st(con); 423 _state st(con);
445 if (!m_expr->parse_non_term(con)) { 424 if (!m_expr->parse_non_term(con)) {
446 con.restore(st); 425 con.restore(st);
@@ -451,17 +430,17 @@ public:
451 return true; 430 return true;
452 } 431 }
453 432
454 //parse terminal 433 // parse terminal
455 virtual bool parse_term(_context& con) const { 434 virtual bool parse_term(_context& con) const {
456 //if parsing of the first fails, restore the context and stop 435 // if parsing of the first fails, restore the context and stop
457 _state st(con); 436 _state st(con);
458 if (!m_expr->parse_term(con)) { 437 if (!m_expr->parse_term(con)) {
459 con.restore(st); 438 con.restore(st);
460 return true; 439 return true;
461 } 440 }
462 441
463 //parse the rest until no more parsing is possible 442 // parse the rest until no more parsing is possible
464 for(;;) { 443 for (;;) {
465 _state st(con); 444 _state st(con);
466 if (!m_expr->parse_term(con)) { 445 if (!m_expr->parse_term(con)) {
467 con.restore(st); 446 con.restore(st);
@@ -473,23 +452,21 @@ public:
473 } 452 }
474}; 453};
475 454
476 455// loop 1
477//loop 1
478class _loop1 : public _unary { 456class _loop1 : public _unary {
479public: 457public:
480 //constructor. 458 // constructor.
481 _loop1(_expr* e) : 459 _loop1(_expr* e)
482 _unary(e) 460 : _unary(e) {
483 {
484 } 461 }
485 462
486 //parse with whitespace 463 // parse with whitespace
487 virtual bool parse_non_term(_context& con) const { 464 virtual bool parse_non_term(_context& con) const {
488 //parse the first; if the first fails, stop 465 // parse the first; if the first fails, stop
489 if (!m_expr->parse_non_term(con)) return false; 466 if (!m_expr->parse_non_term(con)) return false;
490 467
491 //parse the rest until no more parsing is possible 468 // parse the rest until no more parsing is possible
492 for(;;) { 469 for (;;) {
493 _state st(con); 470 _state st(con);
494 if (!m_expr->parse_non_term(con)) { 471 if (!m_expr->parse_non_term(con)) {
495 con.restore(st); 472 con.restore(st);
@@ -500,13 +477,13 @@ public:
500 return true; 477 return true;
501 } 478 }
502 479
503 //parse terminal 480 // parse terminal
504 virtual bool parse_term(_context& con) const { 481 virtual bool parse_term(_context& con) const {
505 //parse the first; if the first fails, stop 482 // parse the first; if the first fails, stop
506 if (!m_expr->parse_term(con)) return false; 483 if (!m_expr->parse_term(con)) return false;
507 484
508 //parse the rest until no more parsing is possible 485 // parse the rest until no more parsing is possible
509 for(;;) { 486 for (;;) {
510 _state st(con); 487 _state st(con);
511 if (!m_expr->parse_term(con)) { 488 if (!m_expr->parse_term(con)) {
512 con.restore(st); 489 con.restore(st);
@@ -518,24 +495,22 @@ public:
518 } 495 }
519}; 496};
520 497
521 498// optional
522//optional
523class _optional : public _unary { 499class _optional : public _unary {
524public: 500public:
525 //constructor. 501 // constructor.
526 _optional(_expr* e) : 502 _optional(_expr* e)
527 _unary(e) 503 : _unary(e) {
528 {
529 } 504 }
530 505
531 //parse with whitespace 506 // parse with whitespace
532 virtual bool parse_non_term(_context& con) const { 507 virtual bool parse_non_term(_context& con) const {
533 _state st(con); 508 _state st(con);
534 if (!m_expr->parse_non_term(con)) con.restore(st); 509 if (!m_expr->parse_non_term(con)) con.restore(st);
535 return true; 510 return true;
536 } 511 }
537 512
538 //parse terminal 513 // parse terminal
539 virtual bool parse_term(_context& con) const { 514 virtual bool parse_term(_context& con) const {
540 _state st(con); 515 _state st(con);
541 if (!m_expr->parse_term(con)) con.restore(st); 516 if (!m_expr->parse_term(con)) con.restore(st);
@@ -543,17 +518,15 @@ public:
543 } 518 }
544}; 519};
545 520
546 521// and
547//and
548class _and : public _unary { 522class _and : public _unary {
549public: 523public:
550 //constructor. 524 // constructor.
551 _and(_expr* e) : 525 _and(_expr* e)
552 _unary(e) 526 : _unary(e) {
553 {
554 } 527 }
555 528
556 //parse with whitespace 529 // parse with whitespace
557 virtual bool parse_non_term(_context& con) const { 530 virtual bool parse_non_term(_context& con) const {
558 _state st(con); 531 _state st(con);
559 bool ok = m_expr->parse_non_term(con); 532 bool ok = m_expr->parse_non_term(con);
@@ -561,7 +534,7 @@ public:
561 return ok; 534 return ok;
562 } 535 }
563 536
564 //parse terminal 537 // parse terminal
565 virtual bool parse_term(_context& con) const { 538 virtual bool parse_term(_context& con) const {
566 _state st(con); 539 _state st(con);
567 bool ok = m_expr->parse_term(con); 540 bool ok = m_expr->parse_term(con);
@@ -570,17 +543,15 @@ public:
570 } 543 }
571}; 544};
572 545
573 546// not
574//not
575class _not : public _unary { 547class _not : public _unary {
576public: 548public:
577 //constructor. 549 // constructor.
578 _not(_expr* e) : 550 _not(_expr* e)
579 _unary(e) 551 : _unary(e) {
580 {
581 } 552 }
582 553
583 //parse with whitespace 554 // parse with whitespace
584 virtual bool parse_non_term(_context& con) const { 555 virtual bool parse_non_term(_context& con) const {
585 _state st(con); 556 _state st(con);
586 bool ok = !m_expr->parse_non_term(con); 557 bool ok = !m_expr->parse_non_term(con);
@@ -588,7 +559,7 @@ public:
588 return ok; 559 return ok;
589 } 560 }
590 561
591 //parse terminal 562 // parse terminal
592 virtual bool parse_term(_context& con) const { 563 virtual bool parse_term(_context& con) const {
593 _state st(con); 564 _state st(con);
594 bool ok = !m_expr->parse_term(con); 565 bool ok = !m_expr->parse_term(con);
@@ -597,24 +568,22 @@ public:
597 } 568 }
598}; 569};
599 570
600 571// newline
601//newline
602class _nl : public _unary { 572class _nl : public _unary {
603public: 573public:
604 //constructor. 574 // constructor.
605 _nl(_expr* e) : 575 _nl(_expr* e)
606 _unary(e) 576 : _unary(e) {
607 {
608 } 577 }
609 578
610 //parse with whitespace 579 // parse with whitespace
611 virtual bool parse_non_term(_context& con) const { 580 virtual bool parse_non_term(_context& con) const {
612 if (!m_expr->parse_non_term(con)) return false; 581 if (!m_expr->parse_non_term(con)) return false;
613 con.next_line(); 582 con.next_line();
614 return true; 583 return true;
615 } 584 }
616 585
617 //parse terminal 586 // parse terminal
618 virtual bool parse_term(_context& con) const { 587 virtual bool parse_term(_context& con) const {
619 if (!m_expr->parse_term(con)) return false; 588 if (!m_expr->parse_term(con)) return false;
620 con.next_line(); 589 con.next_line();
@@ -622,61 +591,56 @@ public:
622 } 591 }
623}; 592};
624 593
625 594// base class for binary expressions
626//base class for binary expressions
627class _binary : public _expr { 595class _binary : public _expr {
628public: 596public:
629 //constructor. 597 // constructor.
630 _binary(_expr* left, _expr* right) : 598 _binary(_expr* left, _expr* right)
631 m_left(left), m_right(right) 599 : m_left(left)
632 { 600 , m_right(right) {
633 } 601 }
634 602
635 //destructor. 603 // destructor.
636 virtual ~_binary() { 604 virtual ~_binary() {
637 delete m_left; 605 delete m_left;
638 delete m_right; 606 delete m_right;
639 } 607 }
640 608
641protected: 609protected:
642 //left and right expressions 610 // left and right expressions
643 _expr* m_left, *m_right; 611 _expr *m_left, *m_right;
644}; 612};
645 613
646 614// sequence
647//sequence
648class _seq : public _binary { 615class _seq : public _binary {
649public: 616public:
650 //constructor. 617 // constructor.
651 _seq(_expr* left, _expr* right) : 618 _seq(_expr* left, _expr* right)
652 _binary(left, right) 619 : _binary(left, right) {
653 {
654 } 620 }
655 621
656 //parse with whitespace 622 // parse with whitespace
657 virtual bool parse_non_term(_context& con) const { 623 virtual bool parse_non_term(_context& con) const {
658 if (!m_left->parse_non_term(con)) return false; 624 if (!m_left->parse_non_term(con)) return false;
659 return m_right->parse_non_term(con); 625 return m_right->parse_non_term(con);
660 } 626 }
661 627
662 //parse terminal 628 // parse terminal
663 virtual bool parse_term(_context& con) const { 629 virtual bool parse_term(_context& con) const {
664 if (!m_left->parse_term(con)) return false; 630 if (!m_left->parse_term(con)) return false;
665 return m_right->parse_term(con); 631 return m_right->parse_term(con);
666 } 632 }
667}; 633};
668 634
669 635// choice
670//choice
671class _choice : public _binary { 636class _choice : public _binary {
672public: 637public:
673 //constructor. 638 // constructor.
674 _choice(_expr* left, _expr* right) : 639 _choice(_expr* left, _expr* right)
675 _binary(left, right) 640 : _binary(left, right) {
676 {
677 } 641 }
678 642
679 //parse with whitespace 643 // parse with whitespace
680 virtual bool parse_non_term(_context& con) const { 644 virtual bool parse_non_term(_context& con) const {
681 _state st(con); 645 _state st(con);
682 if (m_left->parse_non_term(con)) return true; 646 if (m_left->parse_non_term(con)) return true;
@@ -684,7 +648,7 @@ public:
684 return m_right->parse_non_term(con); 648 return m_right->parse_non_term(con);
685 } 649 }
686 650
687 //parse terminal 651 // parse terminal
688 virtual bool parse_term(_context& con) const { 652 virtual bool parse_term(_context& con) const {
689 _state st(con); 653 _state st(con);
690 if (m_left->parse_term(con)) return true; 654 if (m_left->parse_term(con)) return true;
@@ -693,56 +657,52 @@ public:
693 } 657 }
694}; 658};
695 659
696 660// reference to rule
697//reference to rule
698class _ref : public _expr { 661class _ref : public _expr {
699public: 662public:
700 //constructor. 663 // constructor.
701 _ref(rule& r) : 664 _ref(rule& r)
702 m_rule(r) 665 : m_rule(r) {
703 {
704 } 666 }
705 667
706 //parse with whitespace 668 // parse with whitespace
707 virtual bool parse_non_term(_context& con) const { 669 virtual bool parse_non_term(_context& con) const {
708 return con.parse_non_term(m_rule); 670 return con.parse_non_term(m_rule);
709 } 671 }
710 672
711 //parse terminal 673 // parse terminal
712 virtual bool parse_term(_context& con) const { 674 virtual bool parse_term(_context& con) const {
713 return con.parse_term(m_rule); 675 return con.parse_term(m_rule);
714 } 676 }
715 677
716private: 678private:
717 //reference 679 // reference
718 rule &m_rule; 680 rule& m_rule;
719}; 681};
720 682
721 683// eof
722//eof
723class _eof : public _expr { 684class _eof : public _expr {
724public: 685public:
725 //parse with whitespace 686 // parse with whitespace
726 virtual bool parse_non_term(_context& con) const { 687 virtual bool parse_non_term(_context& con) const {
727 return parse_term(con); 688 return parse_term(con);
728 } 689 }
729 690
730 //parse terminal 691 // parse terminal
731 virtual bool parse_term(_context& con) const { 692 virtual bool parse_term(_context& con) const {
732 return con.end(); 693 return con.end();
733 } 694 }
734}; 695};
735 696
736 697// any
737//any
738class _any : public _expr { 698class _any : public _expr {
739public: 699public:
740 //parse with whitespace 700 // parse with whitespace
741 virtual bool parse_non_term(_context& con) const { 701 virtual bool parse_non_term(_context& con) const {
742 return parse_term(con); 702 return parse_term(con);
743 } 703 }
744 704
745 //parse terminal 705 // parse terminal
746 virtual bool parse_term(_context& con) const { 706 virtual bool parse_term(_context& con) const {
747 if (!con.end()) { 707 if (!con.end()) {
748 con.next_col(); 708 con.next_col();
@@ -753,115 +713,108 @@ public:
753 } 713 }
754}; 714};
755 715
756 716// true
757//true
758class _true : public _expr { 717class _true : public _expr {
759public: 718public:
760 //parse with whitespace 719 // parse with whitespace
761 virtual bool parse_non_term(_context&) const { 720 virtual bool parse_non_term(_context&) const {
762 return true; 721 return true;
763 } 722 }
764 723
765 //parse terminal 724 // parse terminal
766 virtual bool parse_term(_context&) const { 725 virtual bool parse_term(_context&) const {
767 return true; 726 return true;
768 } 727 }
769}; 728};
770 729
771 730// false
772//false 731class _false : public _expr {
773class _false: public _expr {
774public: 732public:
775 //parse with whitespace 733 // parse with whitespace
776 virtual bool parse_non_term(_context&) const { 734 virtual bool parse_non_term(_context&) const {
777 return false; 735 return false;
778 } 736 }
779 737
780 //parse terminal 738 // parse terminal
781 virtual bool parse_term(_context&) const { 739 virtual bool parse_term(_context&) const {
782 return false; 740 return false;
783 } 741 }
784}; 742};
785 743
786//exception thrown when left recursion terminates successfully 744// exception thrown when left recursion terminates successfully
787struct _lr_ok { 745struct _lr_ok {
788 rule* m_rule; 746 rule* m_rule;
789 _lr_ok(rule* r) : m_rule(r) {} 747 _lr_ok(rule* r)
748 : m_rule(r) { }
790}; 749};
791 750
792 751// constructor
793//constructor 752_state::_state(_context& con)
794_state::_state(_context& con) : 753 : m_pos(con.m_pos)
795 m_pos(con.m_pos), 754 , m_matches(con.m_matches.size()) {
796 m_matches(con.m_matches.size())
797{
798} 755}
799 756
800 757// parse non-term rule.
801//parse non-term rule.
802bool _context::parse_non_term(rule& r) { 758bool _context::parse_non_term(rule& r) {
803 //save the state of the rule 759 // save the state of the rule
804 rule::_state old_state = r.m_state; 760 rule::_state old_state = r.m_state;
805 761
806 //success/failure result 762 // success/failure result
807 bool ok = false; 763 bool ok = false;
808 764
809 //compute the new position 765 // compute the new position
810 size_t new_pos = m_pos.m_it - m_begin; 766 size_t new_pos = m_pos.m_it - m_begin;
811 767
812 //check if we have left recursion 768 // check if we have left recursion
813 bool lr = new_pos == r.m_state.m_pos; 769 bool lr = new_pos == r.m_state.m_pos;
814 770
815 //update the rule's state 771 // update the rule's state
816 r.m_state.m_pos = new_pos; 772 r.m_state.m_pos = new_pos;
817 773
818 //handle the mode of the rule 774 // handle the mode of the rule
819 switch (r.m_state.m_mode) { 775 switch (r.m_state.m_mode) {
820 //normal parse 776 // normal parse
821 case rule::_PARSE: 777 case rule::_PARSE:
822 if (lr) { 778 if (lr) {
823 //first try to parse the rule by rejecting it, so alternative branches are examined 779 // first try to parse the rule by rejecting it, so alternative branches are examined
824 r.m_state.m_mode = rule::_REJECT; 780 r.m_state.m_mode = rule::_REJECT;
825 ok = _parse_non_term(r); 781 ok = _parse_non_term(r);
826 782
827 //if the first try is successful, try accepting the rule, 783 // if the first try is successful, try accepting the rule,
828 //so other elements of the sequence are parsed 784 // so other elements of the sequence are parsed
829 if (ok) { 785 if (ok) {
830 r.m_state.m_mode = rule::_ACCEPT; 786 r.m_state.m_mode = rule::_ACCEPT;
831 787
832 //loop until no more parsing can be done 788 // loop until no more parsing can be done
833 for(;;) { 789 for (;;) {
834 //store the correct state, in order to backtrack if the call fails 790 // store the correct state, in order to backtrack if the call fails
835 _state st(*this); 791 _state st(*this);
836 792
837 //update the rule position to the current position, 793 // update the rule position to the current position,
838 //because at this state the rule is resolving the left recursion 794 // because at this state the rule is resolving the left recursion
839 r.m_state.m_pos = m_pos.m_it - m_begin; 795 r.m_state.m_pos = m_pos.m_it - m_begin;
840 796
841 //if parsing fails, restore the last good state and stop 797 // if parsing fails, restore the last good state and stop
842 if (!_parse_non_term(r)) { 798 if (!_parse_non_term(r)) {
843 restore(st); 799 restore(st);
844 break; 800 break;
845 } 801 }
846 } 802 }
847 803
848 //since the left recursion was resolved successfully, 804 // since the left recursion was resolved successfully,
849 //return via a non-local exit 805 // return via a non-local exit
850 r.m_state = old_state; 806 r.m_state = old_state;
851 throw _lr_ok(r.this_ptr()); 807 throw _lr_ok(r.this_ptr());
852 } 808 }
853 } 809 } else {
854 else {
855 try { 810 try {
856 ok = _parse_non_term(r); 811 ok = _parse_non_term(r);
857 } 812 } catch (const _lr_ok& ex) {
858 catch (const _lr_ok &ex) { 813 // since left recursions may be mutual, we must test which rule's left recursion
859 //since left recursions may be mutual, we must test which rule's left recursion 814 // was ended successfully
860 //was ended successfully
861 if (ex.m_rule == r.this_ptr()) { 815 if (ex.m_rule == r.this_ptr()) {
862 ok = true; 816 ok = true;
863 } 817 } else {
864 else {
865 r.m_state = old_state; 818 r.m_state = old_state;
866 throw; 819 throw;
867 } 820 }
@@ -869,24 +822,22 @@ bool _context::parse_non_term(rule& r) {
869 } 822 }
870 break; 823 break;
871 824
872 //reject the left recursive rule 825 // reject the left recursive rule
873 case rule::_REJECT: 826 case rule::_REJECT:
874 if (lr) { 827 if (lr) {
875 ok = false; 828 ok = false;
876 } 829 } else {
877 else {
878 r.m_state.m_mode = rule::_PARSE; 830 r.m_state.m_mode = rule::_PARSE;
879 ok = _parse_non_term(r); 831 ok = _parse_non_term(r);
880 r.m_state.m_mode = rule::_REJECT; 832 r.m_state.m_mode = rule::_REJECT;
881 } 833 }
882 break; 834 break;
883 835
884 //accept the left recursive rule 836 // accept the left recursive rule
885 case rule::_ACCEPT: 837 case rule::_ACCEPT:
886 if (lr) { 838 if (lr) {
887 ok = true; 839 ok = true;
888 } 840 } else {
889 else {
890 r.m_state.m_mode = rule::_PARSE; 841 r.m_state.m_mode = rule::_PARSE;
891 ok = _parse_non_term(r); 842 ok = _parse_non_term(r);
892 r.m_state.m_mode = rule::_ACCEPT; 843 r.m_state.m_mode = rule::_ACCEPT;
@@ -894,76 +845,73 @@ bool _context::parse_non_term(rule& r) {
894 break; 845 break;
895 } 846 }
896 847
897 //restore the rule's state 848 // restore the rule's state
898 r.m_state = old_state; 849 r.m_state = old_state;
899 850
900 return ok; 851 return ok;
901} 852}
902 853
903 854// parse term rule.
904//parse term rule.
905bool _context::parse_term(rule& r) { 855bool _context::parse_term(rule& r) {
906 //save the state of the rule 856 // save the state of the rule
907 rule::_state old_state = r.m_state; 857 rule::_state old_state = r.m_state;
908 858
909 //success/failure result 859 // success/failure result
910 bool ok = false; 860 bool ok = false;
911 861
912 //compute the new position 862 // compute the new position
913 size_t new_pos = m_pos.m_it - m_begin; 863 size_t new_pos = m_pos.m_it - m_begin;
914 864
915 //check if we have left recursion 865 // check if we have left recursion
916 bool lr = new_pos == r.m_state.m_pos; 866 bool lr = new_pos == r.m_state.m_pos;
917 867
918 //update the rule's state 868 // update the rule's state
919 r.m_state.m_pos = new_pos; 869 r.m_state.m_pos = new_pos;
920 870
921 //handle the mode of the rule 871 // handle the mode of the rule
922 switch (r.m_state.m_mode) { 872 switch (r.m_state.m_mode) {
923 //normal parse 873 // normal parse
924 case rule::_PARSE: 874 case rule::_PARSE:
925 if (lr) { 875 if (lr) {
926 //first try to parse the rule by rejecting it, so alternative branches are examined 876 // first try to parse the rule by rejecting it, so alternative branches are examined
927 r.m_state.m_mode = rule::_REJECT; 877 r.m_state.m_mode = rule::_REJECT;
928 ok = _parse_term(r); 878 ok = _parse_term(r);
929 879
930 //if the first try is successful, try accepting the rule, 880 // if the first try is successful, try accepting the rule,
931 //so other elements of the sequence are parsed 881 // so other elements of the sequence are parsed
932 if (ok) { 882 if (ok) {
933 r.m_state.m_mode = rule::_ACCEPT; 883 r.m_state.m_mode = rule::_ACCEPT;
934 884
935 //loop until no more parsing can be done 885 // loop until no more parsing can be done
936 for(;;) { 886 for (;;) {
937 //store the correct state, in order to backtrack if the call fails 887 // store the correct state, in order to backtrack if the call fails
938 _state st(*this); 888 _state st(*this);
939 889
940 //update the rule position to the current position, 890 // update the rule position to the current position,
941 //because at this state the rule is resolving the left recursion 891 // because at this state the rule is resolving the left recursion
942 r.m_state.m_pos = m_pos.m_it - m_begin; 892 r.m_state.m_pos = m_pos.m_it - m_begin;
943 893
944 //if parsing fails, restore the last good state and stop 894 // if parsing fails, restore the last good state and stop
945 if (!_parse_term(r)) { 895 if (!_parse_term(r)) {
946 restore(st); 896 restore(st);
947 break; 897 break;
948 } 898 }
949 } 899 }
950 900
951 //since the left recursion was resolved successfully, 901 // since the left recursion was resolved successfully,
952 //return via a non-local exit 902 // return via a non-local exit
953 r.m_state = old_state; 903 r.m_state = old_state;
954 throw _lr_ok(r.this_ptr()); 904 throw _lr_ok(r.this_ptr());
955 } 905 }
956 } else { 906 } else {
957 try { 907 try {
958 ok = _parse_term(r); 908 ok = _parse_term(r);
959 } 909 } catch (const _lr_ok& ex) {
960 catch (const _lr_ok& ex) { 910 // since left recursions may be mutual, we must test which rule's left recursion
961 //since left recursions may be mutual, we must test which rule's left recursion 911 // was ended successfully
962 //was ended successfully
963 if (ex.m_rule == r.this_ptr()) { 912 if (ex.m_rule == r.this_ptr()) {
964 ok = true; 913 ok = true;
965 } 914 } else {
966 else {
967 r.m_state = old_state; 915 r.m_state = old_state;
968 throw; 916 throw;
969 } 917 }
@@ -971,7 +919,7 @@ bool _context::parse_term(rule& r) {
971 } 919 }
972 break; 920 break;
973 921
974 //reject the left recursive rule 922 // reject the left recursive rule
975 case rule::_REJECT: 923 case rule::_REJECT:
976 if (lr) { 924 if (lr) {
977 ok = false; 925 ok = false;
@@ -982,7 +930,7 @@ bool _context::parse_term(rule& r) {
982 } 930 }
983 break; 931 break;
984 932
985 //accept the left recursive rule 933 // accept the left recursive rule
986 case rule::_ACCEPT: 934 case rule::_ACCEPT:
987 if (lr) { 935 if (lr) {
988 ok = true; 936 ok = true;
@@ -994,14 +942,13 @@ bool _context::parse_term(rule& r) {
994 break; 942 break;
995 } 943 }
996 944
997 //restore the rule's state 945 // restore the rule's state
998 r.m_state = old_state; 946 r.m_state = old_state;
999 947
1000 return ok; 948 return ok;
1001} 949}
1002 950
1003 951// parse non-term rule internal.
1004//parse non-term rule internal.
1005bool _context::_parse_non_term(rule& r) { 952bool _context::_parse_non_term(rule& r) {
1006 bool ok = false; 953 bool ok = false;
1007 if (_private::get_parse_proc(r)) { 954 if (_private::get_parse_proc(r)) {
@@ -1016,8 +963,7 @@ bool _context::_parse_non_term(rule& r) {
1016 return ok; 963 return ok;
1017} 964}
1018 965
1019 966// parse term rule internal.
1020//parse term rule internal.
1021bool _context::_parse_term(rule& r) { 967bool _context::_parse_term(rule& r) {
1022 bool ok = false; 968 bool ok = false;
1023 if (_private::get_parse_proc(r)) { 969 if (_private::get_parse_proc(r)) {
@@ -1032,57 +978,46 @@ bool _context::_parse_term(rule& r) {
1032 return ok; 978 return ok;
1033} 979}
1034 980
1035 981// get syntax error
1036//get syntax error
1037static error _syntax_error(_context& con) { 982static error _syntax_error(_context& con) {
1038 return error(con.m_error_pos, con.m_error_pos, ERROR_SYNTAX_ERROR); 983 return error(con.m_error_pos, con.m_error_pos, ERROR_SYNTAX_ERROR);
1039} 984}
1040 985
1041 986// get eof error
1042//get eof error
1043static error _eof_error(_context& con) { 987static error _eof_error(_context& con) {
1044 return error(con.m_error_pos, con.m_error_pos, ERROR_INVALID_EOF); 988 return error(con.m_error_pos, con.m_error_pos, ERROR_INVALID_EOF);
1045} 989}
1046 990
1047
1048/** constructor from input. 991/** constructor from input.
1049 @param i input. 992 @param i input.
1050*/ 993*/
1051pos::pos(input& i) : 994pos::pos(input& i)
1052 m_it(i.begin()), 995 : m_it(i.begin())
1053 m_line(1), 996 , m_line(1)
1054 m_col(1) 997 , m_col(1) {
1055{
1056} 998}
1057 999
1058
1059/** character terminal constructor. 1000/** character terminal constructor.
1060 @param c character. 1001 @param c character.
1061*/ 1002*/
1062expr::expr(char c) : 1003expr::expr(char c)
1063 m_expr(new _char(c)) 1004 : m_expr(new _char(c)) {
1064{
1065} 1005}
1066 1006
1067
1068/** null-terminated string terminal constructor. 1007/** null-terminated string terminal constructor.
1069 @param s null-terminated string. 1008 @param s null-terminated string.
1070*/ 1009*/
1071expr::expr(const char* s) : 1010expr::expr(const char* s)
1072 m_expr(new _string(s)) 1011 : m_expr(new _string(s)) {
1073{
1074} 1012}
1075 1013
1076
1077/** rule reference constructor. 1014/** rule reference constructor.
1078 @param r rule. 1015 @param r rule.
1079*/ 1016*/
1080expr::expr(rule& r) : 1017expr::expr(rule& r)
1081 m_expr(new _ref(r)) 1018 : m_expr(new _ref(r)) {
1082{
1083} 1019}
1084 1020
1085
1086/** creates a zero-or-more loop out of this expression. 1021/** creates a zero-or-more loop out of this expression.
1087 @return a zero-or-more loop expression. 1022 @return a zero-or-more loop expression.
1088*/ 1023*/
@@ -1090,7 +1025,6 @@ expr expr::operator*() const {
1090 return _private::construct_expr(new _loop0(m_expr)); 1025 return _private::construct_expr(new _loop0(m_expr));
1091} 1026}
1092 1027
1093
1094/** creates a one-or-more loop out of this expression. 1028/** creates a one-or-more loop out of this expression.
1095 @return a one-or-more loop expression. 1029 @return a one-or-more loop expression.
1096*/ 1030*/
@@ -1098,7 +1032,6 @@ expr expr::operator+() const {
1098 return _private::construct_expr(new _loop1(m_expr)); 1032 return _private::construct_expr(new _loop1(m_expr));
1099} 1033}
1100 1034
1101
1102/** creates an optional out of this expression. 1035/** creates an optional out of this expression.
1103 @return an optional expression. 1036 @return an optional expression.
1104*/ 1037*/
@@ -1106,7 +1039,6 @@ expr expr::operator-() const {
1106 return _private::construct_expr(new _optional(m_expr)); 1039 return _private::construct_expr(new _optional(m_expr));
1107} 1040}
1108 1041
1109
1110/** creates an AND-expression. 1042/** creates an AND-expression.
1111 @return an AND-expression. 1043 @return an AND-expression.
1112*/ 1044*/
@@ -1114,7 +1046,6 @@ expr expr::operator&() const {
1114 return _private::construct_expr((new _and(m_expr))); 1046 return _private::construct_expr((new _and(m_expr)));
1115} 1047}
1116 1048
1117
1118/** creates a NOT-expression. 1049/** creates a NOT-expression.
1119 @return a NOT-expression. 1050 @return a NOT-expression.
1120*/ 1051*/
@@ -1122,25 +1053,22 @@ expr expr::operator!() const {
1122 return _private::construct_expr(new _not(m_expr)); 1053 return _private::construct_expr(new _not(m_expr));
1123} 1054}
1124 1055
1125
1126/** constructor. 1056/** constructor.
1127 @param b begin position. 1057 @param b begin position.
1128 @param e end position. 1058 @param e end position.
1129*/ 1059*/
1130input_range::input_range(const pos& b, const pos& e) : 1060input_range::input_range(const pos& b, const pos& e)
1131m_begin(b), 1061 : m_begin(b)
1132m_end(e) {} 1062 , m_end(e) { }
1133
1134 1063
1135/** constructor. 1064/** constructor.
1136 @param b begin position. 1065 @param b begin position.
1137 @param e end position. 1066 @param e end position.
1138 @param t error type. 1067 @param t error type.
1139*/ 1068*/
1140error::error(const pos& b, const pos& e, int t) : 1069error::error(const pos& b, const pos& e, int t)
1141input_range(b, e), 1070 : input_range(b, e)
1142m_type(t) {} 1071 , m_type(t) { }
1143
1144 1072
1145/** compare on begin position. 1073/** compare on begin position.
1146 @param e the other error to compare this with. 1074 @param e the other error to compare this with.
@@ -1150,45 +1078,44 @@ bool error::operator<(const error& e) const {
1150 return m_begin.m_it < e.m_begin.m_it; 1078 return m_begin.m_it < e.m_begin.m_it;
1151} 1079}
1152 1080
1153rule::rule() : 1081rule::rule()
1154m_expr(nullptr), 1082 : m_expr(nullptr)
1155m_parse_proc(nullptr) {} 1083 , m_parse_proc(nullptr) { }
1156 1084
1157/** character terminal constructor. 1085/** character terminal constructor.
1158 @param c character. 1086 @param c character.
1159*/ 1087*/
1160rule::rule(char c) : 1088rule::rule(char c)
1161m_expr(new _char(c)), 1089 : m_expr(new _char(c))
1162m_parse_proc(nullptr) {} 1090 , m_parse_proc(nullptr) { }
1163 1091
1164/** null-terminated string terminal constructor. 1092/** null-terminated string terminal constructor.
1165 @param s null-terminated string. 1093 @param s null-terminated string.
1166*/ 1094*/
1167rule::rule(const char* s) : 1095rule::rule(const char* s)
1168m_expr(new _string(s)), 1096 : m_expr(new _string(s))
1169m_parse_proc(nullptr) {} 1097 , m_parse_proc(nullptr) { }
1170 1098
1171/** constructor from expression. 1099/** constructor from expression.
1172 @param e expression. 1100 @param e expression.
1173*/ 1101*/
1174rule::rule(const expr& e) : 1102rule::rule(const expr& e)
1175m_expr(_private::get_expr(e)), 1103 : m_expr(_private::get_expr(e))
1176m_parse_proc(nullptr) {} 1104 , m_parse_proc(nullptr) { }
1177
1178 1105
1179/** constructor from rule. 1106/** constructor from rule.
1180 @param r rule. 1107 @param r rule.
1181*/ 1108*/
1182rule::rule(rule& r) : 1109rule::rule(rule& r)
1183m_expr(new _ref(r)), 1110 : m_expr(new _ref(r))
1184m_parse_proc(nullptr) {} 1111 , m_parse_proc(nullptr) { }
1185 1112
1186rule& rule::operator=(rule& r) { 1113rule& rule::operator=(rule& r) {
1187 m_expr = new _ref(r); 1114 m_expr = new _ref(r);
1188 return *this; 1115 return *this;
1189} 1116}
1190 1117
1191rule &rule::operator=(const expr& e) { 1118rule& rule::operator=(const expr& e) {
1192 m_expr = _private::get_expr(e); 1119 m_expr = _private::get_expr(e);
1193 return *this; 1120 return *this;
1194} 1121}
@@ -1200,14 +1127,12 @@ rule::rule(const rule&) {
1200 throw std::logic_error("invalid operation"); 1127 throw std::logic_error("invalid operation");
1201} 1128}
1202 1129
1203
1204/** deletes the internal object that represents the expression. 1130/** deletes the internal object that represents the expression.
1205*/ 1131 */
1206rule::~rule() { 1132rule::~rule() {
1207 delete m_expr; 1133 delete m_expr;
1208} 1134}
1209 1135
1210
1211/** creates a zero-or-more loop out of this rule. 1136/** creates a zero-or-more loop out of this rule.
1212 @return a zero-or-more loop rule. 1137 @return a zero-or-more loop rule.
1213*/ 1138*/
@@ -1215,7 +1140,6 @@ expr rule::operator*() {
1215 return _private::construct_expr(new _loop0(new _ref(*this))); 1140 return _private::construct_expr(new _loop0(new _ref(*this)));
1216} 1141}
1217 1142
1218
1219/** creates a one-or-more loop out of this rule. 1143/** creates a one-or-more loop out of this rule.
1220 @return a one-or-more loop rule. 1144 @return a one-or-more loop rule.
1221*/ 1145*/
@@ -1223,7 +1147,6 @@ expr rule::operator+() {
1223 return _private::construct_expr(new _loop1(new _ref(*this))); 1147 return _private::construct_expr(new _loop1(new _ref(*this)));
1224} 1148}
1225 1149
1226
1227/** creates an optional out of this rule. 1150/** creates an optional out of this rule.
1228 @return an optional rule. 1151 @return an optional rule.
1229*/ 1152*/
@@ -1231,7 +1154,6 @@ expr rule::operator-() {
1231 return _private::construct_expr(new _optional(new _ref(*this))); 1154 return _private::construct_expr(new _optional(new _ref(*this)));
1232} 1155}
1233 1156
1234
1235/** creates an AND-expression out of this rule. 1157/** creates an AND-expression out of this rule.
1236 @return an AND-expression out of this rule. 1158 @return an AND-expression out of this rule.
1237*/ 1159*/
@@ -1239,7 +1161,6 @@ expr rule::operator&() {
1239 return _private::construct_expr(new _and(new _ref(*this))); 1161 return _private::construct_expr(new _and(new _ref(*this)));
1240} 1162}
1241 1163
1242
1243/** creates a NOT-expression out of this rule. 1164/** creates a NOT-expression out of this rule.
1244 @return a NOT-expression out of this rule. 1165 @return a NOT-expression out of this rule.
1245*/ 1166*/
@@ -1247,7 +1168,6 @@ expr rule::operator!() {
1247 return _private::construct_expr(new _not(new _ref(*this))); 1168 return _private::construct_expr(new _not(new _ref(*this)));
1248} 1169}
1249 1170
1250
1251/** sets the parse procedure. 1171/** sets the parse procedure.
1252 @param p procedure. 1172 @param p procedure.
1253*/ 1173*/
@@ -1256,29 +1176,26 @@ void rule::set_parse_proc(parse_proc p) {
1256 m_parse_proc = p; 1176 m_parse_proc = p;
1257} 1177}
1258 1178
1259
1260/** creates a sequence of expressions. 1179/** creates a sequence of expressions.
1261 @param left left operand. 1180 @param left left operand.
1262 @param right right operand. 1181 @param right right operand.
1263 @return an expression which parses a sequence. 1182 @return an expression which parses a sequence.
1264*/ 1183*/
1265expr operator >> (const expr& left, const expr& right) { 1184expr operator>>(const expr& left, const expr& right) {
1266 return _private::construct_expr( 1185 return _private::construct_expr(
1267 new _seq(_private::get_expr(left), _private::get_expr(right))); 1186 new _seq(_private::get_expr(left), _private::get_expr(right)));
1268} 1187}
1269 1188
1270
1271/** creates a choice of expressions. 1189/** creates a choice of expressions.
1272 @param left left operand. 1190 @param left left operand.
1273 @param right right operand. 1191 @param right right operand.
1274 @return an expression which parses a choice. 1192 @return an expression which parses a choice.
1275*/ 1193*/
1276expr operator | (const expr& left, const expr& right) { 1194expr operator|(const expr& left, const expr& right) {
1277 return _private::construct_expr( 1195 return _private::construct_expr(
1278 new _choice(_private::get_expr(left), _private::get_expr(right))); 1196 new _choice(_private::get_expr(left), _private::get_expr(right)));
1279} 1197}
1280 1198
1281
1282/** converts a parser expression into a terminal. 1199/** converts a parser expression into a terminal.
1283 @param e expression. 1200 @param e expression.
1284 @return an expression which parses a terminal. 1201 @return an expression which parses a terminal.
@@ -1288,7 +1205,6 @@ expr term(const expr& e) {
1288 new _term(_private::get_expr(e))); 1205 new _term(_private::get_expr(e)));
1289} 1206}
1290 1207
1291
1292/** creates a set expression from a null-terminated string. 1208/** creates a set expression from a null-terminated string.
1293 @param s null-terminated string with characters of the set. 1209 @param s null-terminated string with characters of the set.
1294 @return an expression which parses a single character out of a set. 1210 @return an expression which parses a single character out of a set.
@@ -1297,7 +1213,6 @@ expr set(const char* s) {
1297 return _private::construct_expr(new _set(s)); 1213 return _private::construct_expr(new _set(s));
1298} 1214}
1299 1215
1300
1301/** creates a range expression. 1216/** creates a range expression.
1302 @param min min character. 1217 @param min min character.
1303 @param max max character. 1218 @param max max character.
@@ -1307,7 +1222,6 @@ expr range(int min, int max) {
1307 return _private::construct_expr(new _set(min, max)); 1222 return _private::construct_expr(new _set(min, max));
1308} 1223}
1309 1224
1310
1311/** creates an expression which increments the line counter 1225/** creates an expression which increments the line counter
1312 and resets the column counter when the given expression 1226 and resets the column counter when the given expression
1313 is parsed successfully; used for newline characters. 1227 is parsed successfully; used for newline characters.
@@ -1318,7 +1232,6 @@ expr nl(const expr& e) {
1318 return _private::construct_expr(new _nl(_private::get_expr(e))); 1232 return _private::construct_expr(new _nl(_private::get_expr(e)));
1319} 1233}
1320 1234
1321
1322/** creates an expression which tests for the end of input. 1235/** creates an expression which tests for the end of input.
1323 @return an expression that handles the end of input. 1236 @return an expression that handles the end of input.
1324*/ 1237*/
@@ -1326,7 +1239,6 @@ expr eof() {
1326 return _private::construct_expr(new _eof()); 1239 return _private::construct_expr(new _eof());
1327} 1240}
1328 1241
1329
1330/** creates a not expression. 1242/** creates a not expression.
1331 @param e expression. 1243 @param e expression.
1332 @return the appropriate expression. 1244 @return the appropriate expression.
@@ -1335,7 +1247,6 @@ expr not_(const expr& e) {
1335 return !e; 1247 return !e;
1336} 1248}
1337 1249
1338
1339/** creates an and expression. 1250/** creates an and expression.
1340 @param e expression. 1251 @param e expression.
1341 @return the appropriate expression. 1252 @return the appropriate expression.
@@ -1344,7 +1255,6 @@ expr and_(const expr& e) {
1344 return &e; 1255 return &e;
1345} 1256}
1346 1257
1347
1348/** creates an expression that parses any character. 1258/** creates an expression that parses any character.
1349 @return the appropriate expression. 1259 @return the appropriate expression.
1350*/ 1260*/
@@ -1352,28 +1262,24 @@ expr any() {
1352 return _private::construct_expr(new _any()); 1262 return _private::construct_expr(new _any());
1353} 1263}
1354 1264
1355
1356/** parsing succeeds without consuming any input. 1265/** parsing succeeds without consuming any input.
1357*/ 1266 */
1358expr true_() { 1267expr true_() {
1359 return _private::construct_expr(new _true()); 1268 return _private::construct_expr(new _true());
1360} 1269}
1361 1270
1362
1363/** parsing fails without consuming any input. 1271/** parsing fails without consuming any input.
1364*/ 1272 */
1365expr false_() { 1273expr false_() {
1366 return _private::construct_expr(new _false()); 1274 return _private::construct_expr(new _false());
1367} 1275}
1368 1276
1369
1370/** parse with target expression and let user handle result. 1277/** parse with target expression and let user handle result.
1371*/ 1278 */
1372expr user(const expr& e, const user_handler& handler) { 1279expr user(const expr& e, const user_handler& handler) {
1373 return _private::construct_expr(new _user(_private::get_expr(e), handler)); 1280 return _private::construct_expr(new _user(_private::get_expr(e), handler));
1374} 1281}
1375 1282
1376
1377/** parses the given input. 1283/** parses the given input.
1378 The parse procedures of each rule parsed are executed 1284 The parse procedures of each rule parsed are executed
1379 before this function returns, if parsing succeeds. 1285 before this function returns, if parsing succeeds.
@@ -1384,16 +1290,16 @@ expr user(const expr& e, const user_handler& handler) {
1384 @return true on parsing success, false on failure. 1290 @return true on parsing success, false on failure.
1385*/ 1291*/
1386bool parse(input& i, rule& g, error_list& el, void* d, void* ud) { 1292bool parse(input& i, rule& g, error_list& el, void* d, void* ud) {
1387 //prepare context 1293 // prepare context
1388 _context con(i, ud); 1294 _context con(i, ud);
1389 1295
1390 //parse grammar 1296 // parse grammar
1391 if (!con.parse_non_term(g)) { 1297 if (!con.parse_non_term(g)) {
1392 el.push_back(_syntax_error(con)); 1298 el.push_back(_syntax_error(con));
1393 return false; 1299 return false;
1394 } 1300 }
1395 1301
1396 //if end is not reached, there was an error 1302 // if end is not reached, there was an error
1397 if (!con.end()) { 1303 if (!con.end()) {
1398 if (con.m_error_pos.m_it < con.m_end) { 1304 if (con.m_error_pos.m_it < con.m_end) {
1399 el.push_back(_syntax_error(con)); 1305 el.push_back(_syntax_error(con));
@@ -1403,10 +1309,9 @@ bool parse(input& i, rule& g, error_list& el, void* d, void* ud) {
1403 return false; 1309 return false;
1404 } 1310 }
1405 1311
1406 //success; execute the parse procedures 1312 // success; execute the parse procedures
1407 con.do_parse_procs(d); 1313 con.do_parse_procs(d);
1408 return true; 1314 return true;
1409} 1315}
1410 1316
1411 1317} // namespace parserlib
1412} //namespace parserlib
diff --git a/src/yuescript/parser.hpp b/src/yuescript/parser.hpp
index f70475f..eed0bff 100644
--- a/src/yuescript/parser.hpp
+++ b/src/yuescript/parser.hpp
@@ -11,24 +11,22 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
11 11
12#pragma once 12#pragma once
13 13
14 14// gcc chokes without rule::rule(const rule &),
15//gcc chokes without rule::rule(const rule &), 15// msvc complains when rule::rule(const rule &) is defined.
16//msvc complains when rule::rule(const rule &) is defined.
17#ifdef _MSC_VER 16#ifdef _MSC_VER
18#pragma warning (disable: 4521) 17#pragma warning(disable : 4521)
19#endif 18#endif
20 19
21
22#include <vector>
23#include <string>
24#include <list>
25#include <functional>
26#include <codecvt> 20#include <codecvt>
21#include <functional>
22#include <list>
27#include <locale> 23#include <locale>
24#include <string>
25#include <vector>
28 26
29namespace parserlib { 27namespace parserlib {
30 28
31///type of the parser's input. 29/// type of the parser's input.
32typedef std::basic_string<wchar_t> input; 30typedef std::basic_string<wchar_t> input;
33typedef input::iterator input_it; 31typedef input::iterator input_it;
34typedef std::wstring_convert<std::codecvt_utf8_utf16<input::value_type>> Converter; 32typedef std::wstring_convert<std::codecvt_utf8_utf16<input::value_type>> Converter;
@@ -38,7 +36,6 @@ class _expr;
38class _context; 36class _context;
39class rule; 37class rule;
40 38
41
42struct item_t { 39struct item_t {
43 input_it begin; 40 input_it begin;
44 input_it end; 41 input_it end;
@@ -46,31 +43,31 @@ struct item_t {
46}; 43};
47typedef std::function<bool(const item_t&)> user_handler; 44typedef std::function<bool(const item_t&)> user_handler;
48 45
49 46/// position into the input.
50///position into the input.
51class pos { 47class pos {
52public: 48public:
53 ///interator into the input. 49 /// interator into the input.
54 input::iterator m_it; 50 input::iterator m_it;
55 51
56 ///line. 52 /// line.
57 int m_line; 53 int m_line;
58 54
59 ///column. 55 /// column.
60 int m_col; 56 int m_col;
61 57
62 ///null constructor. 58 /// null constructor.
63 pos():m_line(0),m_col(0) {} 59 pos()
60 : m_line(0)
61 , m_col(0) { }
64 62
65 /** constructor from input. 63 /** constructor from input.
66 @param i input. 64 @param i input.
67 */ 65 */
68 pos(input &i); 66 pos(input& i);
69}; 67};
70 68
71
72/** a grammar expression. 69/** a grammar expression.
73*/ 70 */
74class expr { 71class expr {
75public: 72public:
76 /** character terminal constructor. 73 /** character terminal constructor.
@@ -114,19 +111,19 @@ public:
114 expr operator!() const; 111 expr operator!() const;
115 112
116private: 113private:
117 //internal expression 114 // internal expression
118 _expr* m_expr; 115 _expr* m_expr;
119 116
120 //internal constructor from internal expression 117 // internal constructor from internal expression
121 expr(_expr* e) : m_expr(e) {} 118 expr(_expr* e)
119 : m_expr(e) { }
122 120
123 //assignment not allowed 121 // assignment not allowed
124 expr& operator=(expr&); 122 expr& operator=(expr&);
125 123
126 friend class _private; 124 friend class _private;
127}; 125};
128 126
129
130/** type of procedure to invoke when a rule is successfully parsed. 127/** type of procedure to invoke when a rule is successfully parsed.
131 @param b begin position of input. 128 @param b begin position of input.
132 @param e end position of input. 129 @param e end position of input.
@@ -134,20 +131,19 @@ private:
134*/ 131*/
135typedef void (*parse_proc)(const pos& b, const pos& e, void* d); 132typedef void (*parse_proc)(const pos& b, const pos& e, void* d);
136 133
137 134/// input range.
138///input range.
139class input_range { 135class input_range {
140public: 136public:
141 virtual ~input_range() {} 137 virtual ~input_range() { }
142 138
143 ///begin position. 139 /// begin position.
144 pos m_begin; 140 pos m_begin;
145 141
146 ///end position. 142 /// end position.
147 pos m_end; 143 pos m_end;
148 144
149 ///empty constructor. 145 /// empty constructor.
150 input_range() {} 146 input_range() { }
151 147
152 /** constructor. 148 /** constructor.
153 @param b begin position. 149 @param b begin position.
@@ -156,24 +152,22 @@ public:
156 input_range(const pos& b, const pos& e); 152 input_range(const pos& b, const pos& e);
157}; 153};
158 154
159 155/// enum with error types.
160///enum with error types.
161enum ERROR_TYPE { 156enum ERROR_TYPE {
162 ///syntax error 157 /// syntax error
163 ERROR_SYNTAX_ERROR = 1, 158 ERROR_SYNTAX_ERROR = 1,
164 159
165 ///invalid end of file 160 /// invalid end of file
166 ERROR_INVALID_EOF, 161 ERROR_INVALID_EOF,
167 162
168 ///first user error 163 /// first user error
169 ERROR_USER = 100 164 ERROR_USER = 100
170}; 165};
171 166
172 167/// error.
173///error.
174class error : public input_range { 168class error : public input_range {
175public: 169public:
176 ///type 170 /// type
177 int m_type; 171 int m_type;
178 172
179 /** constructor. 173 /** constructor.
@@ -190,13 +184,11 @@ public:
190 bool operator<(const error& e) const; 184 bool operator<(const error& e) const;
191}; 185};
192 186
193 187/// type of error list.
194///type of error list.
195typedef std::list<error> error_list; 188typedef std::list<error> error_list;
196 189
197
198/** represents a rule. 190/** represents a rule.
199*/ 191 */
200class rule { 192class rule {
201public: 193public:
202 /** character terminal constructor. 194 /** character terminal constructor.
@@ -227,7 +219,7 @@ public:
227 rule(const rule& r); 219 rule(const rule& r);
228 220
229 /** deletes the internal object that represents the expression. 221 /** deletes the internal object that represents the expression.
230 */ 222 */
231 ~rule(); 223 ~rule();
232 224
233 /** creates a zero-or-more loop out of this rule. 225 /** creates a zero-or-more loop out of this rule.
@@ -270,40 +262,40 @@ public:
270 rule& operator=(const expr&); 262 rule& operator=(const expr&);
271 263
272private: 264private:
273 //mode 265 // mode
274 enum _MODE { 266 enum _MODE {
275 _PARSE, 267 _PARSE,
276 _REJECT, 268 _REJECT,
277 _ACCEPT 269 _ACCEPT
278 }; 270 };
279 271
280 //state 272 // state
281 struct _state { 273 struct _state {
282 //position in source code, relative to start 274 // position in source code, relative to start
283 size_t m_pos; 275 size_t m_pos;
284 276
285 //mode 277 // mode
286 _MODE m_mode; 278 _MODE m_mode;
287 279
288 //constructor 280 // constructor
289 _state(size_t pos = -1, _MODE mode = _PARSE) : 281 _state(size_t pos = -1, _MODE mode = _PARSE)
290 m_pos(pos), m_mode(mode) {} 282 : m_pos(pos)
283 , m_mode(mode) { }
291 }; 284 };
292 285
293 //internal expression 286 // internal expression
294 _expr* m_expr; 287 _expr* m_expr;
295 288
296 //associated parse procedure. 289 // associated parse procedure.
297 parse_proc m_parse_proc; 290 parse_proc m_parse_proc;
298 291
299 //state 292 // state
300 _state m_state; 293 _state m_state;
301 294
302 friend class _private; 295 friend class _private;
303 friend class _context; 296 friend class _context;
304}; 297};
305 298
306
307/** creates a sequence of expressions. 299/** creates a sequence of expressions.
308 @param left left operand. 300 @param left left operand.
309 @param right right operand. 301 @param right right operand.
@@ -311,7 +303,6 @@ private:
311*/ 303*/
312expr operator>>(const expr& left, const expr& right); 304expr operator>>(const expr& left, const expr& right);
313 305
314
315/** creates a choice of expressions. 306/** creates a choice of expressions.
316 @param left left operand. 307 @param left left operand.
317 @param right right operand. 308 @param right right operand.
@@ -319,21 +310,18 @@ expr operator>>(const expr& left, const expr& right);
319*/ 310*/
320expr operator|(const expr& left, const expr& right); 311expr operator|(const expr& left, const expr& right);
321 312
322
323/** converts a parser expression into a terminal. 313/** converts a parser expression into a terminal.
324 @param e expression. 314 @param e expression.
325 @return an expression which parses a terminal. 315 @return an expression which parses a terminal.
326*/ 316*/
327expr term(const expr& e); 317expr term(const expr& e);
328 318
329
330/** creates a set expression from a null-terminated string. 319/** creates a set expression from a null-terminated string.
331 @param s null-terminated string with characters of the set. 320 @param s null-terminated string with characters of the set.
332 @return an expression which parses a single character out of a set. 321 @return an expression which parses a single character out of a set.
333*/ 322*/
334expr set(const char* s); 323expr set(const char* s);
335 324
336
337/** creates a range expression. 325/** creates a range expression.
338 @param min min character. 326 @param min min character.
339 @param max max character. 327 @param max max character.
@@ -341,7 +329,6 @@ expr set(const char* s);
341*/ 329*/
342expr range(int min, int max); 330expr range(int min, int max);
343 331
344
345/** creates an expression which increments the line counter 332/** creates an expression which increments the line counter
346 and resets the column counter when the given expression 333 and resets the column counter when the given expression
347 is parsed successfully; used for newline characters. 334 is parsed successfully; used for newline characters.
@@ -350,48 +337,40 @@ expr range(int min, int max);
350*/ 337*/
351expr nl(const expr& e); 338expr nl(const expr& e);
352 339
353
354/** creates an expression which tests for the end of input. 340/** creates an expression which tests for the end of input.
355 @return an expression that handles the end of input. 341 @return an expression that handles the end of input.
356*/ 342*/
357expr eof(); 343expr eof();
358 344
359
360/** creates a not expression. 345/** creates a not expression.
361 @param e expression. 346 @param e expression.
362 @return the appropriate expression. 347 @return the appropriate expression.
363*/ 348*/
364expr not_(const expr& e); 349expr not_(const expr& e);
365 350
366
367/** creates an and expression. 351/** creates an and expression.
368 @param e expression. 352 @param e expression.
369 @return the appropriate expression. 353 @return the appropriate expression.
370*/ 354*/
371expr and_(const expr& e); 355expr and_(const expr& e);
372 356
373
374/** creates an expression that parses any character. 357/** creates an expression that parses any character.
375 @return the appropriate expression. 358 @return the appropriate expression.
376*/ 359*/
377expr any(); 360expr any();
378 361
379
380/** parsing succeeds without consuming any input. 362/** parsing succeeds without consuming any input.
381*/ 363 */
382expr true_(); 364expr true_();
383 365
384
385/** parsing fails without consuming any input. 366/** parsing fails without consuming any input.
386*/ 367 */
387expr false_(); 368expr false_();
388 369
389
390/** parse with target expression and let user handle result. 370/** parse with target expression and let user handle result.
391*/ 371 */
392expr user(const expr& e, const user_handler& handler); 372expr user(const expr& e, const user_handler& handler);
393 373
394
395/** parses the given input. 374/** parses the given input.
396 The parse procedures of each rule parsed are executed 375 The parse procedures of each rule parsed are executed
397 before this function returns, if parsing succeeds. 376 before this function returns, if parsing succeeds.
@@ -403,20 +382,19 @@ expr user(const expr& e, const user_handler& handler);
403*/ 382*/
404bool parse(input& i, rule& g, error_list& el, void* d, void* ud); 383bool parse(input& i, rule& g, error_list& el, void* d, void* ud);
405 384
406
407/** output the specific input range to the specific stream. 385/** output the specific input range to the specific stream.
408 @param stream stream. 386 @param stream stream.
409 @param ir input range. 387 @param ir input range.
410 @return the stream. 388 @return the stream.
411*/ 389*/
412template <class T> T& operator<<(T& stream, const input_range& ir) { 390template <class T>
413 for(input::const_iterator it = ir.m_begin.m_it; 391T& operator<<(T& stream, const input_range& ir) {
414 it != ir.m_end.m_it; 392 for (input::const_iterator it = ir.m_begin.m_it;
415 ++it) { 393 it != ir.m_end.m_it;
416 stream << (typename T::char_type)*it; 394 ++it) {
395 stream << (typename T::char_type) * it;
417 } 396 }
418 return stream; 397 return stream;
419} 398}
420 399
421 400} // namespace parserlib
422} //namespace parserlib
diff --git a/src/yuescript/yue_ast.h b/src/yuescript/yue_ast.h
index 620dfcc..386fa28 100755
--- a/src/yuescript/yue_ast.h
+++ b/src/yuescript/yue_ast.h
@@ -14,18 +14,16 @@ namespace parserlib {
14using namespace std::string_view_literals; 14using namespace std::string_view_literals;
15 15
16#define AST_LEAF(type) \ 16#define AST_LEAF(type) \
17COUNTER_INC; \ 17 COUNTER_INC; \
18class type##_t : public ast_node \ 18 class type##_t : public ast_node { \
19{ \ 19 public: \
20public: \ 20 virtual int getId() const override { return COUNTER_READ; }
21 virtual int getId() const override { return COUNTER_READ; }
22 21
23#define AST_NODE(type) \ 22#define AST_NODE(type) \
24COUNTER_INC; \ 23 COUNTER_INC; \
25class type##_t : public ast_container \ 24 class type##_t : public ast_container { \
26{ \ 25 public: \
27public: \ 26 virtual int getId() const override { return COUNTER_READ; }
28 virtual int getId() const override { return COUNTER_READ; }
29 27
30#define AST_MEMBER(type, ...) \ 28#define AST_MEMBER(type, ...) \
31 type##_t() { \ 29 type##_t() { \
@@ -34,8 +32,12 @@ public: \
34 32
35#define AST_END(type, name) \ 33#define AST_END(type, name) \
36 virtual const std::string_view getName() const override { return name; } \ 34 virtual const std::string_view getName() const override { return name; } \
37}; \ 35 } \
38template<> constexpr int id<type##_t>() { return COUNTER_READ; } 36 ; \
37 template <> \
38 constexpr int id<type##_t>() { return COUNTER_READ; }
39
40// clang-format off
39 41
40AST_LEAF(Num) 42AST_LEAF(Num)
41AST_END(Num, "num"sv) 43AST_END(Num, "num"sv)
@@ -849,4 +851,6 @@ AST_NODE(File)
849 AST_MEMBER(File, &block) 851 AST_MEMBER(File, &block)
850AST_END(File, "file"sv) 852AST_END(File, "file"sv)
851 853
854// clang-format on
855
852} // namespace parserlib 856} // namespace parserlib
diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp
index b730a9f..17979ab 100755
--- a/src/yuescript/yue_compiler.cpp
+++ b/src/yuescript/yue_compiler.cpp
@@ -6,23 +6,23 @@ The above copyright notice and this permission notice shall be included in all c
6 6
7THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.*/ 7THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.*/
8 8
9#include <memory>
10#include <optional>
11#include <set>
12#include <stack>
9#include <string> 13#include <string>
10#include <unordered_set>
11#include <unordered_map> 14#include <unordered_map>
12#include <stack> 15#include <unordered_set>
13#include <vector> 16#include <vector>
14#include <memory>
15#include <set>
16#include <optional>
17 17
18#include "yuescript/yue_parser.h"
19#include "yuescript/yue_compiler.h" 18#include "yuescript/yue_compiler.h"
19#include "yuescript/yue_parser.h"
20 20
21#ifndef YUE_NO_MACRO 21#ifndef YUE_NO_MACRO
22 22
23extern "C" { 23extern "C" {
24#include "lua.h"
25#include "lauxlib.h" 24#include "lauxlib.h"
25#include "lua.h"
26#include "lualib.h" 26#include "lualib.h"
27} // extern "C" 27} // extern "C"
28 28
@@ -30,9 +30,9 @@ extern "C" {
30#define YUE_MODULE "__yue_modules__" 30#define YUE_MODULE "__yue_modules__"
31 31
32#if LUA_VERSION_NUM > 501 32#if LUA_VERSION_NUM > 501
33 #ifndef LUA_COMPAT_5_1 33#ifndef LUA_COMPAT_5_1
34 #define lua_objlen lua_rawlen 34#define lua_objlen lua_rawlen
35 #endif // LUA_COMPAT_5_1 35#endif // LUA_COMPAT_5_1
36#endif // LUA_VERSION_NUM 36#endif // LUA_VERSION_NUM
37 37
38#endif // YUE_NO_MACRO 38#endif // YUE_NO_MACRO
@@ -40,17 +40,22 @@ extern "C" {
40namespace yue { 40namespace yue {
41 41
42#define BLOCK_START do { 42#define BLOCK_START do {
43#define BLOCK_END } while (false); 43#define BLOCK_END \
44#define BREAK_IF(cond) if (cond) break 44 } \
45 45 while (false) \
46#define _DEFER(code,line) std::shared_ptr<void> _defer_##line(nullptr, [&](auto){code;}) 46 ;
47#define DEFER(code) _DEFER(code,__LINE__) 47#define BREAK_IF(cond) \
48#define YUEE(msg,node) throw std::logic_error( \ 48 if (cond) break
49
50#define _DEFER(code, line) std::shared_ptr<void> _defer_##line(nullptr, [&](auto) { code; })
51#define DEFER(code) _DEFER(code, __LINE__)
52#define YUEE(msg, node) throw std::logic_error( \
49 _info.errorMessage( \ 53 _info.errorMessage( \
50 "[File] "s + __FILE__ \ 54 "[File] "s + __FILE__ \
51 + ",\n[Func] "s + __FUNCTION__ \ 55 + ",\n[Func] "s + __FUNCTION__ \
52 + ",\n[Line] "s + std::to_string(__LINE__) \ 56 + ",\n[Line] "s + std::to_string(__LINE__) \
53 + ",\n[Error] "s + msg, node)) 57 + ",\n[Error] "s + msg, \
58 node))
54 59
55typedef std::list<std::string> str_list; 60typedef std::list<std::string> str_list;
56 61
@@ -62,9 +67,9 @@ public:
62#ifndef YUE_NO_MACRO 67#ifndef YUE_NO_MACRO
63 YueCompilerImpl(lua_State* sharedState, 68 YueCompilerImpl(lua_State* sharedState,
64 const std::function<void(void*)>& luaOpen, 69 const std::function<void(void*)>& luaOpen,
65 bool sameModule): 70 bool sameModule)
66 L(sharedState), 71 : L(sharedState)
67 _luaOpen(luaOpen) { 72 , _luaOpen(luaOpen) {
68 BLOCK_START 73 BLOCK_START
69 BREAK_IF(!sameModule); 74 BREAK_IF(!sameModule);
70 BREAK_IF(!L); 75 BREAK_IF(!L);
@@ -153,8 +158,7 @@ public:
153 std::tie(line, col) = var.second; 158 std::tie(line, col) = var.second;
154 globals->push_back({var.first, line, col}); 159 globals->push_back({var.first, line, col});
155 } 160 }
156 std::sort(globals->begin(), globals->end(), [](const GlobalVar& varA, const GlobalVar& varB) 161 std::sort(globals->begin(), globals->end(), [](const GlobalVar& varA, const GlobalVar& varB) {
157 {
158 if (varA.line < varB.line) { 162 if (varA.line < varB.line) {
159 return true; 163 return true;
160 } else if (varA.line == varB.line) { 164 } else if (varA.line == varB.line) {
@@ -222,6 +226,7 @@ public:
222 } 226 }
223#endif // YUE_NO_MACRO 227#endif // YUE_NO_MACRO
224 } 228 }
229
225private: 230private:
226#ifndef YUE_NO_MACRO 231#ifndef YUE_NO_MACRO
227 bool _stateOwner = false; 232 bool _stateOwner = false;
@@ -234,22 +239,20 @@ private:
234 YueParser _parser; 239 YueParser _parser;
235 ParseInfo _info; 240 ParseInfo _info;
236 int _indentOffset = 0; 241 int _indentOffset = 0;
237 struct VarArgState 242 struct VarArgState {
238 {
239 bool hasVar; 243 bool hasVar;
240 bool usedVar; 244 bool usedVar;
241 }; 245 };
242 std::stack<VarArgState> _varArgs; 246 std::stack<VarArgState> _varArgs;
243 std::stack<bool> _enableReturn; 247 std::stack<bool> _enableReturn;
244 std::stack<std::string> _withVars; 248 std::stack<std::string> _withVars;
245 struct ContinueVar 249 struct ContinueVar {
246 {
247 std::string var; 250 std::string var;
248 ast_ptr<false, ExpListAssign_t> condAssign; 251 ast_ptr<false, ExpListAssign_t> condAssign;
249 }; 252 };
250 std::stack<ContinueVar> _continueVars; 253 std::stack<ContinueVar> _continueVars;
251 std::list<std::unique_ptr<input>> _codeCache; 254 std::list<std::unique_ptr<input>> _codeCache;
252 std::unordered_map<std::string,std::pair<int, int>> _globals; 255 std::unordered_map<std::string, std::pair<int, int>> _globals;
253 std::ostringstream _buf; 256 std::ostringstream _buf;
254 std::ostringstream _joinBuf; 257 std::ostringstream _joinBuf;
255 const std::string _newLine = "\n"; 258 const std::string _newLine = "\n";
@@ -271,7 +274,7 @@ private:
271 }; 274 };
272 struct Scope { 275 struct Scope {
273 GlobalMode mode = GlobalMode::None; 276 GlobalMode mode = GlobalMode::None;
274 std::unique_ptr<std::unordered_map<std::string,VarType>> vars; 277 std::unique_ptr<std::unordered_map<std::string, VarType>> vars;
275 std::unique_ptr<std::unordered_set<std::string>> allows; 278 std::unique_ptr<std::unordered_set<std::string>> allows;
276 std::unique_ptr<std::unordered_set<std::string>> globals; 279 std::unique_ptr<std::unordered_set<std::string>> globals;
277 }; 280 };
@@ -312,7 +315,7 @@ private:
312 315
313 void pushScope() { 316 void pushScope() {
314 _scopes.emplace_back(); 317 _scopes.emplace_back();
315 _scopes.back().vars = std::make_unique<std::unordered_map<std::string,VarType>>(); 318 _scopes.back().vars = std::make_unique<std::unordered_map<std::string, VarType>>();
316 } 319 }
317 320
318 void popScope() { 321 void popScope() {
@@ -377,7 +380,7 @@ private:
377 bool isConst(const std::string& name) const { 380 bool isConst(const std::string& name) const {
378 bool isConst = false; 381 bool isConst = false;
379 decltype(_scopes.back().allows.get()) allows = nullptr; 382 decltype(_scopes.back().allows.get()) allows = nullptr;
380 for (auto it = _scopes.rbegin(); it != _scopes.rend(); ++it) { 383 for (auto it = _scopes.rbegin(); it != _scopes.rend(); ++it) {
381 if (it->allows) allows = it->allows.get(); 384 if (it->allows) allows = it->allows.get();
382 } 385 }
383 bool checkShadowScopeOnly = false; 386 bool checkShadowScopeOnly = false;
@@ -524,8 +527,10 @@ private:
524 } 527 }
525 528
526 std::string join(const str_list& items) { 529 std::string join(const str_list& items) {
527 if (items.empty()) return Empty; 530 if (items.empty())
528 else if (items.size() == 1) return items.front(); 531 return Empty;
532 else if (items.size() == 1)
533 return items.front();
529 for (const auto& item : items) { 534 for (const auto& item : items) {
530 _joinBuf << item; 535 _joinBuf << item;
531 } 536 }
@@ -536,8 +541,10 @@ private:
536 } 541 }
537 542
538 std::string join(const str_list& items, std::string_view sep) { 543 std::string join(const str_list& items, std::string_view sep) {
539 if (items.empty()) return Empty; 544 if (items.empty())
540 else if (items.size() == 1) return items.front(); 545 return Empty;
546 else if (items.size() == 1)
547 return items.front();
541 std::string sepStr = std::string(sep); 548 std::string sepStr = std::string(sep);
542 auto begin = ++items.begin(); 549 auto begin = ++items.begin();
543 _joinBuf << items.front(); 550 _joinBuf << items.front();
@@ -659,7 +666,8 @@ private:
659 666
660 Statement_t* lastStatementFrom(const node_container& stmts) const { 667 Statement_t* lastStatementFrom(const node_container& stmts) const {
661 if (!stmts.empty()) { 668 if (!stmts.empty()) {
662 auto it = stmts.end(); --it; 669 auto it = stmts.end();
670 --it;
663 while (!static_cast<Statement_t*>(*it)->content && it != stmts.begin()) { 671 while (!static_cast<Statement_t*>(*it)->content && it != stmts.begin()) {
664 --it; 672 --it;
665 } 673 }
@@ -864,15 +872,17 @@ private:
864 case id<SelfName_t>(): 872 case id<SelfName_t>():
865 return true; 873 return true;
866 } 874 }
867 } else switch (firstItem->getId()) { 875 } else
868 case id<DotChainItem_t>(): 876 switch (firstItem->getId()) {
869 case id<Exp_t>(): 877 case id<DotChainItem_t>():
870 return true; 878 case id<Exp_t>():
871 } 879 return true;
880 }
872 } else { 881 } else {
873 if (std::find_if(chainItems.begin(), chainItems.end(), [](ast_node* node) { 882 if (std::find_if(chainItems.begin(), chainItems.end(), [](ast_node* node) {
874 return ast_is<existential_op_t>(node); 883 return ast_is<existential_op_t>(node);
875 }) != chainItems.end()) { 884 })
885 != chainItems.end()) {
876 return false; 886 return false;
877 } 887 }
878 auto lastItem = chainItems.back(); 888 auto lastItem = chainItems.back();
@@ -1155,7 +1165,7 @@ private:
1155 break; 1165 break;
1156 } 1166 }
1157 } 1167 }
1158 } else if (expList->exprs.size() == 1){ 1168 } else if (expList->exprs.size() == 1) {
1159 auto exp = static_cast<Exp_t*>(expList->exprs.back()); 1169 auto exp = static_cast<Exp_t*>(expList->exprs.back());
1160 if (isPureBackcall(exp)) { 1170 if (isPureBackcall(exp)) {
1161 transformExp(exp, out, ExpUsage::Common); 1171 transformExp(exp, out, ExpUsage::Common);
@@ -1277,7 +1287,7 @@ private:
1277 } 1287 }
1278 } 1288 }
1279 } 1289 }
1280 if (!defs.empty()) _buf << indent() << "local "sv << join(defs,", "sv); 1290 if (!defs.empty()) _buf << indent() << "local "sv << join(defs, ", "sv);
1281 } 1291 }
1282 } 1292 }
1283 return clearBuf(); 1293 return clearBuf();
@@ -1392,15 +1402,15 @@ private:
1392 auto j = values.begin(); 1402 auto j = values.begin();
1393 auto je = --values.end(); 1403 auto je = --values.end();
1394 while (j != je) { 1404 while (j != je) {
1395 ++i; ++j; 1405 ++i;
1406 ++j;
1396 } 1407 }
1397 bool holdItem = false; 1408 bool holdItem = false;
1398 for (auto it = i; it != exprs.end(); ++it) { 1409 for (auto it = i; it != exprs.end(); ++it) {
1399 BLOCK_START 1410 BLOCK_START
1400 auto value = singleValueFrom(*it); 1411 auto value = singleValueFrom(*it);
1401 BREAK_IF(!value); 1412 BREAK_IF(!value);
1402 if (value->item.is<simple_table_t>() || 1413 if (value->item.is<simple_table_t>() || value->getByPath<SimpleValue_t, TableLit_t>()) {
1403 value->getByPath<SimpleValue_t, TableLit_t>()) {
1404 holdItem = true; 1414 holdItem = true;
1405 break; 1415 break;
1406 } 1416 }
@@ -1524,7 +1534,8 @@ private:
1524 popScope(); 1534 popScope();
1525 temp.push_back(indent() + "end"s + nlr(x)); 1535 temp.push_back(indent() + "end"s + nlr(x));
1526 } 1536 }
1527 } else break; 1537 } else
1538 break;
1528 auto newExpList = x->new_ptr<ExpList_t>(); 1539 auto newExpList = x->new_ptr<ExpList_t>();
1529 auto newAssign = x->new_ptr<Assign_t>(); 1540 auto newAssign = x->new_ptr<Assign_t>();
1530 auto newAssignment = x->new_ptr<ExpListAssign_t>(); 1541 auto newAssignment = x->new_ptr<ExpListAssign_t>();
@@ -1946,13 +1957,12 @@ private:
1946 switch (pair->getId()) { 1957 switch (pair->getId()) {
1947 case id<Exp_t>(): { 1958 case id<Exp_t>(): {
1948 ++index; 1959 ++index;
1949 if (!isAssignable(static_cast<Exp_t*>(pair))) { 1960 if (!isAssignable(static_cast<Exp_t*>(pair))) {
1950 throw std::logic_error(_info.errorMessage("can't destructure value"sv, pair)); 1961 throw std::logic_error(_info.errorMessage("can't destructure value"sv, pair));
1951 } 1962 }
1952 auto value = singleValueFrom(pair); 1963 auto value = singleValueFrom(pair);
1953 auto item = value->item.get(); 1964 auto item = value->item.get();
1954 if (ast_is<simple_table_t>(item) || 1965 if (ast_is<simple_table_t>(item) || item->getByPath<TableLit_t>()) {
1955 item->getByPath<TableLit_t>()) {
1956 auto subPairs = destructFromExp(pair, optional); 1966 auto subPairs = destructFromExp(pair, optional);
1957 for (auto& p : subPairs) { 1967 for (auto& p : subPairs) {
1958 pairs.push_back({p.target, p.targetVar, 1968 pairs.push_back({p.target, p.targetVar,
@@ -1963,12 +1973,10 @@ private:
1963 auto exp = static_cast<Exp_t*>(pair); 1973 auto exp = static_cast<Exp_t*>(pair);
1964 auto varName = singleVariableFrom(exp, false); 1974 auto varName = singleVariableFrom(exp, false);
1965 if (varName == "_"sv) break; 1975 if (varName == "_"sv) break;
1966 pairs.push_back({ 1976 pairs.push_back({exp,
1967 exp,
1968 varName, 1977 varName,
1969 '[' + std::to_string(index) + ']', 1978 '[' + std::to_string(index) + ']',
1970 nullptr 1979 nullptr});
1971 });
1972 } 1980 }
1973 break; 1981 break;
1974 } 1982 }
@@ -1994,37 +2002,30 @@ private:
1994 if (auto exp = np->value.as<Exp_t>()) { 2002 if (auto exp = np->value.as<Exp_t>()) {
1995 if (!isAssignable(exp)) throw std::logic_error(_info.errorMessage("can't destructure value"sv, exp)); 2003 if (!isAssignable(exp)) throw std::logic_error(_info.errorMessage("can't destructure value"sv, exp));
1996 auto item = singleValueFrom(exp)->item.get(); 2004 auto item = singleValueFrom(exp)->item.get();
1997 if (ast_is<simple_table_t>(item) || 2005 if (ast_is<simple_table_t>(item) || item->getByPath<TableLit_t>()) {
1998 item->getByPath<TableLit_t>()) {
1999 auto subPairs = destructFromExp(exp, optional); 2006 auto subPairs = destructFromExp(exp, optional);
2000 for (auto& p : subPairs) { 2007 for (auto& p : subPairs) {
2001 pairs.push_back({ 2008 pairs.push_back({p.target,
2002 p.target,
2003 p.targetVar, 2009 p.targetVar,
2004 keyName + sep + p.structure, 2010 keyName + sep + p.structure,
2005 p.defVal 2011 p.defVal});
2006 });
2007 } 2012 }
2008 } else { 2013 } else {
2009 auto varName = singleVariableFrom(exp, false); 2014 auto varName = singleVariableFrom(exp, false);
2010 pairs.push_back({ 2015 pairs.push_back({exp,
2011 exp,
2012 varName, 2016 varName,
2013 keyName, 2017 keyName,
2014 nullptr 2018 nullptr});
2015 });
2016 } 2019 }
2017 break; 2020 break;
2018 } 2021 }
2019 if (np->value.is<TableBlock_t>()) { 2022 if (np->value.is<TableBlock_t>()) {
2020 auto subPairs = destructFromExp(np->value, optional); 2023 auto subPairs = destructFromExp(np->value, optional);
2021 for (auto& p : subPairs) { 2024 for (auto& p : subPairs) {
2022 pairs.push_back({ 2025 pairs.push_back({p.target,
2023 p.target,
2024 p.targetVar, 2026 p.targetVar,
2025 keyName + sep + p.structure, 2027 keyName + sep + p.structure,
2026 p.defVal 2028 p.defVal});
2027 });
2028 } 2029 }
2029 } 2030 }
2030 break; 2031 break;
@@ -2034,16 +2035,14 @@ private:
2034 ++index; 2035 ++index;
2035 auto subPairs = destructFromExp(tb, optional); 2036 auto subPairs = destructFromExp(tb, optional);
2036 for (auto& p : subPairs) { 2037 for (auto& p : subPairs) {
2037 pairs.push_back({ 2038 pairs.push_back({p.target,
2038 p.target,
2039 p.targetVar, 2039 p.targetVar,
2040 '[' + std::to_string(index) + ']' + sep + p.structure, 2040 '[' + std::to_string(index) + ']' + sep + p.structure,
2041 p.defVal 2041 p.defVal});
2042 });
2043 } 2042 }
2044 break; 2043 break;
2045 } 2044 }
2046 case id<default_pair_t>() : { 2045 case id<default_pair_t>(): {
2047 auto dp = static_cast<default_pair_t*>(pair); 2046 auto dp = static_cast<default_pair_t*>(pair);
2048 if (auto exp = dp->key.as<Exp_t>()) { 2047 if (auto exp = dp->key.as<Exp_t>()) {
2049 ++index; 2048 ++index;
@@ -2052,17 +2051,14 @@ private:
2052 } 2051 }
2053 auto value = singleValueFrom(exp); 2052 auto value = singleValueFrom(exp);
2054 auto item = value->item.get(); 2053 auto item = value->item.get();
2055 if (ast_is<simple_table_t>(item) || 2054 if (ast_is<simple_table_t>(item) || item->getByPath<TableLit_t>()) {
2056 item->getByPath<TableLit_t>()) {
2057 throw std::logic_error(_info.errorMessage("invalid use of default value"sv, dp->defVal)); 2055 throw std::logic_error(_info.errorMessage("invalid use of default value"sv, dp->defVal));
2058 } else { 2056 } else {
2059 auto varName = singleVariableFrom(exp, false); 2057 auto varName = singleVariableFrom(exp, false);
2060 pairs.push_back({ 2058 pairs.push_back({exp,
2061 exp,
2062 varName, 2059 varName,
2063 '[' + std::to_string(index) + ']', 2060 '[' + std::to_string(index) + ']',
2064 dp->defVal 2061 dp->defVal});
2065 });
2066 } 2062 }
2067 break; 2063 break;
2068 } 2064 }
@@ -2081,19 +2077,15 @@ private:
2081 if (auto exp = dp->value.get()) { 2077 if (auto exp = dp->value.get()) {
2082 if (!isAssignable(exp)) throw std::logic_error(_info.errorMessage("can't destructure value"sv, exp)); 2078 if (!isAssignable(exp)) throw std::logic_error(_info.errorMessage("can't destructure value"sv, exp));
2083 auto varName = singleVariableFrom(exp, false); 2079 auto varName = singleVariableFrom(exp, false);
2084 pairs.push_back({ 2080 pairs.push_back({exp,
2085 exp,
2086 varName, 2081 varName,
2087 keyName, 2082 keyName,
2088 dp->defVal 2083 dp->defVal});
2089 });
2090 } else { 2084 } else {
2091 pairs.push_back({ 2085 pairs.push_back({toAst<Exp_t>(valueStr, dp).get(),
2092 toAst<Exp_t>(valueStr, dp).get(),
2093 valueStr, 2086 valueStr,
2094 keyName, 2087 keyName,
2095 dp->defVal 2088 dp->defVal});
2096 });
2097 } 2089 }
2098 break; 2090 break;
2099 } 2091 }
@@ -2157,12 +2149,10 @@ private:
2157 value->item.set(simpleValue); 2149 value->item.set(simpleValue);
2158 auto subPairs = destructFromExp(newExp(value, subMetaDestruct), optional); 2150 auto subPairs = destructFromExp(newExp(value, subMetaDestruct), optional);
2159 for (const auto& p : subPairs) { 2151 for (const auto& p : subPairs) {
2160 pairs.push_back({ 2152 pairs.push_back({p.target,
2161 p.target,
2162 p.targetVar, 2153 p.targetVar,
2163 ".#"s + (p.structure.empty() ? Empty : sep + p.structure), 2154 ".#"s + (p.structure.empty() ? Empty : sep + p.structure),
2164 p.defVal 2155 p.defVal});
2165 });
2166 } 2156 }
2167 } 2157 }
2168 return pairs; 2158 return pairs;
@@ -2373,8 +2363,7 @@ private:
2373 if (!leftValue) throw std::logic_error(_info.errorMessage("left hand expression is not assignable"sv, leftExp)); 2363 if (!leftValue) throw std::logic_error(_info.errorMessage("left hand expression is not assignable"sv, leftExp));
2374 auto chain = leftValue->item.as<ChainValue_t>(); 2364 auto chain = leftValue->item.as<ChainValue_t>();
2375 if (!chain) throw std::logic_error(_info.errorMessage("left hand expression is not assignable"sv, leftValue)); 2365 if (!chain) throw std::logic_error(_info.errorMessage("left hand expression is not assignable"sv, leftValue));
2376 BLOCK_START 2366 BLOCK_START {
2377 {
2378 auto dot = ast_cast<DotChainItem_t>(chain->items.back()); 2367 auto dot = ast_cast<DotChainItem_t>(chain->items.back());
2379 if (dot && dot->name.is<Metatable_t>()) { 2368 if (dot && dot->name.is<Metatable_t>()) {
2380 throw std::logic_error(_info.errorMessage("can not apply update to a metatable"sv, leftExp)); 2369 throw std::logic_error(_info.errorMessage("can not apply update to a metatable"sv, leftExp));
@@ -2457,10 +2446,11 @@ private:
2457 right = '(' + right + ')'; 2446 right = '(' + right + ')';
2458 } 2447 }
2459 _buf << join(temp); 2448 _buf << join(temp);
2460 if (!defs.empty()) _buf << defs; 2449 if (!defs.empty())
2461 else _buf << indent() << left; 2450 _buf << defs;
2462 _buf << " = "sv << left << 2451 else
2463 ' ' << op << ' ' << right << nll(assignment); 2452 _buf << indent() << left;
2453 _buf << " = "sv << left << ' ' << op << ' ' << right << nll(assignment);
2464 out.push_back(clearBuf()); 2454 out.push_back(clearBuf());
2465 break; 2455 break;
2466 } 2456 }
@@ -2709,7 +2699,8 @@ private:
2709 } else { 2699 } else {
2710 auto x = values.front(); 2700 auto x = values.front();
2711 auto arg = newExp(static_cast<unary_exp_t*>(x), x); 2701 auto arg = newExp(static_cast<unary_exp_t*>(x), x);
2712 auto begin = values.begin(); begin++; 2702 auto begin = values.begin();
2703 begin++;
2713 for (auto it = begin; it != values.end(); ++it) { 2704 for (auto it = begin; it != values.end(); ++it) {
2714 auto unary = static_cast<unary_exp_t*>(*it); 2705 auto unary = static_cast<unary_exp_t*>(*it);
2715 auto value = static_cast<Value_t*>(singleUnaryExpFrom(unary) ? unary->expos.back() : nullptr); 2706 auto value = static_cast<Value_t*>(singleUnaryExpFrom(unary) ? unary->expos.back() : nullptr);
@@ -2943,7 +2934,7 @@ private:
2943 } 2934 }
2944 } 2935 }
2945 2936
2946 void transformCallable(Callable_t* callable, str_list& out, const ast_sel<false,Invoke_t,InvokeArgs_t>& invoke = {}) { 2937 void transformCallable(Callable_t* callable, str_list& out, const ast_sel<false, Invoke_t, InvokeArgs_t>& invoke = {}) {
2947 auto item = callable->item.get(); 2938 auto item = callable->item.get();
2948 switch (item->getId()) { 2939 switch (item->getId()) {
2949 case id<Variable_t>(): { 2940 case id<Variable_t>(): {
@@ -3042,9 +3033,7 @@ private:
3042 temp.push_back(Empty); 3033 temp.push_back(Empty);
3043 } 3034 }
3044 auto& bodyCodes = temp.back(); 3035 auto& bodyCodes = temp.back();
3045 _buf << "function("sv << 3036 _buf << "function("sv << (isFatArrow ? "self"s : Empty) << ')';
3046 (isFatArrow ? "self"s : Empty) <<
3047 ')';
3048 if (!bodyCodes.empty()) { 3037 if (!bodyCodes.empty()) {
3049 _buf << nll(funLit) << bodyCodes; 3038 _buf << nll(funLit) << bodyCodes;
3050 popScope(); 3039 popScope();
@@ -3077,7 +3066,7 @@ private:
3077 } 3066 }
3078 const auto& nodes = block->statements.objects(); 3067 const auto& nodes = block->statements.objects();
3079 LocalMode mode = LocalMode::None; 3068 LocalMode mode = LocalMode::None;
3080 Local_t* any = nullptr, *capital = nullptr; 3069 Local_t *any = nullptr, *capital = nullptr;
3081 for (auto it = nodes.begin(); it != nodes.end(); ++it) { 3070 for (auto it = nodes.begin(); it != nodes.end(); ++it) {
3082 auto node = *it; 3071 auto node = *it;
3083 auto stmt = static_cast<Statement_t*>(node); 3072 auto stmt = static_cast<Statement_t*>(node);
@@ -3086,7 +3075,8 @@ private:
3086 bool cond = false; 3075 bool cond = false;
3087 BLOCK_START 3076 BLOCK_START
3088 BREAK_IF(it == nodes.begin()); 3077 BREAK_IF(it == nodes.begin());
3089 auto last = it; --last; 3078 auto last = it;
3079 --last;
3090 auto lst = static_cast<Statement_t*>(*last); 3080 auto lst = static_cast<Statement_t*>(*last);
3091 if (lst->appendix) { 3081 if (lst->appendix) {
3092 throw std::logic_error(_info.errorMessage("statement decorator must be placed at the end of pipe chain"sv, lst->appendix.get())); 3082 throw std::logic_error(_info.errorMessage("statement decorator must be placed at the end of pipe chain"sv, lst->appendix.get()));
@@ -3104,7 +3094,8 @@ private:
3104 BLOCK_END 3094 BLOCK_END
3105 if (!cond) throw std::logic_error(_info.errorMessage("pipe chain must be following a value"sv, x)); 3095 if (!cond) throw std::logic_error(_info.errorMessage("pipe chain must be following a value"sv, x));
3106 stmt->content.set(nullptr); 3096 stmt->content.set(nullptr);
3107 auto next = it; ++next; 3097 auto next = it;
3098 ++next;
3108 BLOCK_START 3099 BLOCK_START
3109 BREAK_IF(next == nodes.end()); 3100 BREAK_IF(next == nodes.end());
3110 BREAK_IF(!static_cast<Statement_t*>(*next)->content.as<PipeBody_t>()); 3101 BREAK_IF(!static_cast<Statement_t*>(*next)->content.as<PipeBody_t>());
@@ -3122,7 +3113,8 @@ private:
3122 ast_ptr<false, Exp_t> arg; 3113 ast_ptr<false, Exp_t> arg;
3123 { 3114 {
3124 auto block = x->new_ptr<Block_t>(); 3115 auto block = x->new_ptr<Block_t>();
3125 auto next = it; ++next; 3116 auto next = it;
3117 ++next;
3126 if (next != nodes.end()) { 3118 if (next != nodes.end()) {
3127 for (auto i = next; i != nodes.end(); ++i) { 3119 for (auto i = next; i != nodes.end(); ++i) {
3128 block->statements.push_back(*i); 3120 block->statements.push_back(*i);
@@ -3240,7 +3232,8 @@ private:
3240 for (const auto& destruct : info.destructures) 3232 for (const auto& destruct : info.destructures)
3241 for (const auto& item : destruct.items) 3233 for (const auto& item : destruct.items)
3242 if (!item.targetVar.empty()) { 3234 if (!item.targetVar.empty()) {
3243 if (std::isupper(item.targetVar[0]) && capital) { capital->decls.push_back(item.targetVar); 3235 if (std::isupper(item.targetVar[0]) && capital) {
3236 capital->decls.push_back(item.targetVar);
3244 } else if (any) { 3237 } else if (any) {
3245 any->decls.push_back(item.targetVar); 3238 any->decls.push_back(item.targetVar);
3246 } 3239 }
@@ -3249,7 +3242,8 @@ private:
3249 if (info.assignment) { 3242 if (info.assignment) {
3250 auto defs = transformAssignDefs(info.assignment->expList, DefOp::Get); 3243 auto defs = transformAssignDefs(info.assignment->expList, DefOp::Get);
3251 for (const auto& def : defs) { 3244 for (const auto& def : defs) {
3252 if (std::isupper(def[0]) && capital) { capital->decls.push_back(def); 3245 if (std::isupper(def[0]) && capital) {
3246 capital->decls.push_back(def);
3253 } else if (any) { 3247 } else if (any) {
3254 any->decls.push_back(def); 3248 any->decls.push_back(def);
3255 } 3249 }
@@ -3295,9 +3289,7 @@ private:
3295 BREAK_IF(!last); 3289 BREAK_IF(!last);
3296 auto x = last; 3290 auto x = last;
3297 auto expList = expListFrom(last); 3291 auto expList = expListFrom(last);
3298 BREAK_IF(!expList || 3292 BREAK_IF(!expList || (last->appendix && last->appendix->item.is<CompInner_t>()));
3299 (last->appendix &&
3300 last->appendix->item.is<CompInner_t>()));
3301 auto expListLow = x->new_ptr<ExpListLow_t>(); 3293 auto expListLow = x->new_ptr<ExpListLow_t>();
3302 expListLow->exprs.dup(expList->exprs); 3294 expListLow->exprs.dup(expList->exprs);
3303 auto returnNode = x->new_ptr<Return_t>(); 3295 auto returnNode = x->new_ptr<Return_t>();
@@ -3764,14 +3756,18 @@ private:
3764 _buf << indent() << "end"sv << nll(def); 3756 _buf << indent() << "end"sv << nll(def);
3765 temp.back() = clearBuf(); 3757 temp.back() = clearBuf();
3766 } 3758 }
3767 if (varNames.empty()) varNames = arg.name; 3759 if (varNames.empty())
3768 else varNames.append(", "s + arg.name); 3760 varNames = arg.name;
3761 else
3762 varNames.append(", "s + arg.name);
3769 } 3763 }
3770 if (argDefList->varArg) { 3764 if (argDefList->varArg) {
3771 auto& arg = argItems.emplace_back(); 3765 auto& arg = argItems.emplace_back();
3772 arg.name = "..."sv; 3766 arg.name = "..."sv;
3773 if (varNames.empty()) varNames = arg.name; 3767 if (varNames.empty())
3774 else varNames.append(", "s + arg.name); 3768 varNames = arg.name;
3769 else
3770 varNames.append(", "s + arg.name);
3775 _varArgs.top().hasVar = true; 3771 _varArgs.top().hasVar = true;
3776 } 3772 }
3777 if (assignSelf) { 3773 if (assignSelf) {
@@ -3790,7 +3786,7 @@ private:
3790 out.push_back(join(temp)); 3786 out.push_back(join(temp));
3791 } 3787 }
3792 3788
3793 void transformSelfName(SelfName_t* selfName, str_list& out, const ast_sel<false,Invoke_t,InvokeArgs_t>& invoke = {}) { 3789 void transformSelfName(SelfName_t* selfName, str_list& out, const ast_sel<false, Invoke_t, InvokeArgs_t>& invoke = {}) {
3794 auto x = selfName; 3790 auto x = selfName;
3795 auto name = selfName->name.get(); 3791 auto name = selfName->name.get();
3796 switch (name->getId()) { 3792 switch (name->getId()) {
@@ -3899,7 +3895,7 @@ private:
3899 pushScope(); 3895 pushScope();
3900 } 3896 }
3901 auto partOne = x->new_ptr<ChainValue_t>(); 3897 auto partOne = x->new_ptr<ChainValue_t>();
3902 for (auto it = chainList.begin();it != opIt;++it) { 3898 for (auto it = chainList.begin(); it != opIt; ++it) {
3903 partOne->items.push_back(*it); 3899 partOne->items.push_back(*it);
3904 } 3900 }
3905 BLOCK_START 3901 BLOCK_START
@@ -3972,7 +3968,8 @@ private:
3972 partOne->items.clear(); 3968 partOne->items.clear();
3973 partOne->items.push_back(toAst<Callable_t>(objVar, x)); 3969 partOne->items.push_back(toAst<Callable_t>(objVar, x));
3974 partOne->items.push_back(dotItem); 3970 partOne->items.push_back(dotItem);
3975 auto it = opIt; ++it; 3971 auto it = opIt;
3972 ++it;
3976 if (it != chainList.end() && ast_is<Invoke_t, InvokeArgs_t>(*it)) { 3973 if (it != chainList.end() && ast_is<Invoke_t, InvokeArgs_t>(*it)) {
3977 3974
3978 if (auto invoke = ast_cast<Invoke_t>(*it)) { 3975 if (auto invoke = ast_cast<Invoke_t>(*it)) {
@@ -3999,7 +3996,7 @@ private:
3999 pushScope(); 3996 pushScope();
4000 auto partTwo = x->new_ptr<ChainValue_t>(); 3997 auto partTwo = x->new_ptr<ChainValue_t>();
4001 partTwo->items.push_back(toAst<Callable_t>(objVar, x)); 3998 partTwo->items.push_back(toAst<Callable_t>(objVar, x));
4002 for (auto it = ++opIt;it != chainList.end();++it) { 3999 for (auto it = ++opIt; it != chainList.end(); ++it) {
4003 partTwo->items.push_back(*it); 4000 partTwo->items.push_back(*it);
4004 } 4001 }
4005 switch (usage) { 4002 switch (usage) {
@@ -4248,7 +4245,8 @@ private:
4248 case id<ColonChainItem_t>(): { 4245 case id<ColonChainItem_t>(): {
4249 auto colonItem = static_cast<ColonChainItem_t*>(item); 4246 auto colonItem = static_cast<ColonChainItem_t*>(item);
4250 auto current = it; 4247 auto current = it;
4251 auto next = current; ++next; 4248 auto next = current;
4249 ++next;
4252 auto followItem = next != chainList.end() ? *next : nullptr; 4250 auto followItem = next != chainList.end() ? *next : nullptr;
4253 if (current != chainList.begin()) { 4251 if (current != chainList.begin()) {
4254 --current; 4252 --current;
@@ -4272,7 +4270,7 @@ private:
4272 switch (chainList.front()->getId()) { 4270 switch (chainList.front()->getId()) {
4273 case id<DotChainItem_t>(): 4271 case id<DotChainItem_t>():
4274 case id<ColonChainItem_t>(): 4272 case id<ColonChainItem_t>():
4275 chainValue->items.push_back(toAst<Callable_t>(_withVars.top(), x)); 4273 chainValue->items.push_back(toAst<Callable_t>(_withVars.top(), x));
4276 break; 4274 break;
4277 } 4275 }
4278 for (auto i = chainList.begin(); i != current; ++i) { 4276 for (auto i = chainList.begin(); i != current; ++i) {
@@ -4366,7 +4364,8 @@ private:
4366 transformSlice(static_cast<Slice_t*>(item), temp); 4364 transformSlice(static_cast<Slice_t*>(item), temp);
4367 break; 4365 break;
4368 case id<Callable_t>(): { 4366 case id<Callable_t>(): {
4369 auto next = it; ++next; 4367 auto next = it;
4368 ++next;
4370 auto followItem = next != chainList.end() ? *next : nullptr; 4369 auto followItem = next != chainList.end() ? *next : nullptr;
4371 ast_sel<false, Invoke_t, InvokeArgs_t> invoke; 4370 ast_sel<false, Invoke_t, InvokeArgs_t> invoke;
4372 if (ast_is<Invoke_t, InvokeArgs_t>(followItem)) { 4371 if (ast_is<Invoke_t, InvokeArgs_t>(followItem)) {
@@ -4464,7 +4463,7 @@ private:
4464 return Empty; 4463 return Empty;
4465 } 4464 }
4466 4465
4467 std::tuple<std::string,std::string,str_list> expandMacroStr(ChainValue_t* chainValue) { 4466 std::tuple<std::string, std::string, str_list> expandMacroStr(ChainValue_t* chainValue) {
4468 const auto& chainList = chainValue->items.objects(); 4467 const auto& chainList = chainValue->items.objects();
4469 auto x = ast_to<Callable_t>(chainList.front())->item.to<MacroName_t>(); 4468 auto x = ast_to<Callable_t>(chainList.front())->item.to<MacroName_t>();
4470 auto macroName = _parser.toString(x->name); 4469 auto macroName = _parser.toString(x->name);
@@ -4490,7 +4489,7 @@ private:
4490 auto item = *(++chainList.begin()); 4489 auto item = *(++chainList.begin());
4491 if (auto invoke = ast_cast<Invoke_t>(item)) { 4490 if (auto invoke = ast_cast<Invoke_t>(item)) {
4492 args = &invoke->args.objects(); 4491 args = &invoke->args.objects();
4493 } else if (auto invoke = ast_cast<InvokeArgs_t>(item)){ 4492 } else if (auto invoke = ast_cast<InvokeArgs_t>(item)) {
4494 args = &invoke->args.objects(); 4493 args = &invoke->args.objects();
4495 } 4494 }
4496 } 4495 }
@@ -4599,7 +4598,7 @@ private:
4599 return {type, codes, std::move(localVars)}; 4598 return {type, codes, std::move(localVars)};
4600 } 4599 }
4601 4600
4602 std::tuple<ast_ptr<false,ast_node>, std::unique_ptr<input>, std::string, str_list> expandMacro(ChainValue_t* chainValue, ExpUsage usage, bool allowBlockMacroReturn) { 4601 std::tuple<ast_ptr<false, ast_node>, std::unique_ptr<input>, std::string, str_list> expandMacro(ChainValue_t* chainValue, ExpUsage usage, bool allowBlockMacroReturn) {
4603 auto x = ast_to<Callable_t>(chainValue->items.front())->item.to<MacroName_t>(); 4602 auto x = ast_to<Callable_t>(chainValue->items.front())->item.to<MacroName_t>();
4604 const auto& chainList = chainValue->items.objects(); 4603 const auto& chainList = chainValue->items.objects();
4605 std::string type, codes; 4604 std::string type, codes;
@@ -4928,10 +4927,10 @@ private:
4928 forceAddToScope(indexVar); 4927 forceAddToScope(indexVar);
4929 temp.push_back(indent() + "local "s + indexVar + " = 1"s + nll(item)); 4928 temp.push_back(indent() + "local "s + indexVar + " = 1"s + nll(item));
4930 _buf << "for "sv << keyVar << ',' << valueVar << " in pairs "sv << objVar 4929 _buf << "for "sv << keyVar << ',' << valueVar << " in pairs "sv << objVar
4931 << "\n\tif "sv << indexVar << "=="sv << keyVar 4930 << "\n\tif "sv << indexVar << "=="sv << keyVar
4932 << "\n\t\t"sv << tableVar << "[]="sv << valueVar 4931 << "\n\t\t"sv << tableVar << "[]="sv << valueVar
4933 << "\n\t\t"sv << indexVar << "+=1"sv 4932 << "\n\t\t"sv << indexVar << "+=1"sv
4934 << "\n\telse "sv << tableVar << '[' << keyVar << "]="sv << valueVar; 4933 << "\n\telse "sv << tableVar << '[' << keyVar << "]="sv << valueVar;
4935 auto forEach = toAst<ForEach_t>(clearBuf(), item); 4934 auto forEach = toAst<ForEach_t>(clearBuf(), item);
4936 transformForEach(forEach, temp); 4935 transformForEach(forEach, temp);
4937 break; 4936 break;
@@ -4998,7 +4997,7 @@ private:
4998 auto chainValue = value->item.as<ChainValue_t>(); 4997 auto chainValue = value->item.as<ChainValue_t>();
4999 BREAK_IF(!chainValue); 4998 BREAK_IF(!chainValue);
5000 BREAK_IF(chainValue->items.size() != 1); 4999 BREAK_IF(chainValue->items.size() != 1);
5001 BREAK_IF((!chainValue->getByPath<Callable_t,VarArg_t>())); 5000 BREAK_IF((!chainValue->getByPath<Callable_t, VarArg_t>()));
5002 auto indexVar = getUnusedName("_index_"); 5001 auto indexVar = getUnusedName("_index_");
5003 _buf << "for "sv << indexVar << "=1,select '#',...\n\t"sv << tableVar << "[]= select "sv << indexVar << ",..."sv; 5002 _buf << "for "sv << indexVar << "=1,select '#',...\n\t"sv << tableVar << "[]= select "sv << indexVar << ",..."sv;
5004 transformFor(toAst<For_t>(clearBuf(), item), temp); 5003 transformFor(toAst<For_t>(clearBuf(), item), temp);
@@ -5098,8 +5097,7 @@ private:
5098 transformAssignment(assignment, temp); 5097 transformAssignment(assignment, temp);
5099 popScope(); 5098 popScope();
5100 out.push_back(join(temp)); 5099 out.push_back(join(temp));
5101 out.back() = indent() + "do"s + nll(x) + 5100 out.back() = indent() + "do"s + nll(x) + out.back() + indent() + "end"s + nlr(x);
5102 out.back() + indent() + "end"s + nlr(x);
5103 break; 5101 break;
5104 } 5102 }
5105 case ExpUsage::Return: 5103 case ExpUsage::Return:
@@ -5205,14 +5203,15 @@ private:
5205 str_list tmp; 5203 str_list tmp;
5206 if (!metatable->pairs.empty()) { 5204 if (!metatable->pairs.empty()) {
5207 transform_simple_table(metatable, tmp); 5205 transform_simple_table(metatable, tmp);
5208 } else switch (metatableItem->getId()) { 5206 } else
5209 case id<Exp_t>(): 5207 switch (metatableItem->getId()) {
5210 transformExp(static_cast<Exp_t*>(metatableItem.get()), tmp, ExpUsage::Closure); 5208 case id<Exp_t>():
5211 break; 5209 transformExp(static_cast<Exp_t*>(metatableItem.get()), tmp, ExpUsage::Closure);
5212 case id<TableBlock_t>(): 5210 break;
5213 transformTableBlock(static_cast<TableBlock_t*>(metatableItem.get()), tmp); 5211 case id<TableBlock_t>():
5214 break; 5212 transformTableBlock(static_cast<TableBlock_t*>(metatableItem.get()), tmp);
5215 } 5213 break;
5214 }
5216 tabStr += tmp.back(); 5215 tabStr += tmp.back();
5217 tabStr += ')'; 5216 tabStr += ')';
5218 out.push_back(tabStr); 5217 out.push_back(tabStr);
@@ -5349,9 +5348,7 @@ private:
5349 assignment->action.set(assign); 5348 assignment->action.set(assign);
5350 transformAssignment(assignment, temp); 5349 transformAssignment(assignment, temp);
5351 popScope(); 5350 popScope();
5352 out.back() = indent() + "do"s + nll(comp) + 5351 out.back() = indent() + "do"s + nll(comp) + out.back() + temp.back() + indent() + "end"s + nlr(comp);
5353 out.back() + temp.back() +
5354 indent() + "end"s + nlr(comp);
5355 break; 5352 break;
5356 } 5353 }
5357 case ExpUsage::Return: 5354 case ExpUsage::Return:
@@ -5529,7 +5526,7 @@ private:
5529 } 5526 }
5530 5527
5531 void transformInvokeArgs(InvokeArgs_t* invokeArgs, str_list& out) { 5528 void transformInvokeArgs(InvokeArgs_t* invokeArgs, str_list& out) {
5532 if (invokeArgs->args.size() > 1) { 5529 if (invokeArgs->args.size() > 1) {
5533 /* merge all the key-value pairs into one table 5530 /* merge all the key-value pairs into one table
5534 from arguments in the end */ 5531 from arguments in the end */
5535 auto lastArg = invokeArgs->args.back(); 5532 auto lastArg = invokeArgs->args.back();
@@ -5614,18 +5611,18 @@ private:
5614 return traversal::Stop == body->traverse([&](ast_node* node) { 5611 return traversal::Stop == body->traverse([&](ast_node* node) {
5615 if (auto stmt = ast_cast<Statement_t>(node)) { 5612 if (auto stmt = ast_cast<Statement_t>(node)) {
5616 if (stmt->content.is<BreakLoop_t>()) { 5613 if (stmt->content.is<BreakLoop_t>()) {
5617 return _parser.toString(stmt->content) == "continue"sv ? 5614 return _parser.toString(stmt->content) == "continue"sv ? traversal::Stop : traversal::Return;
5618 traversal::Stop : traversal::Return;
5619 } else if (expListFrom(stmt)) { 5615 } else if (expListFrom(stmt)) {
5620 return traversal::Continue; 5616 return traversal::Continue;
5621 } 5617 }
5622 return traversal::Return; 5618 return traversal::Return;
5623 } else switch (node->getId()) { 5619 } else
5624 case id<FunLit_t>(): 5620 switch (node->getId()) {
5625 case id<Invoke_t>(): 5621 case id<FunLit_t>():
5626 case id<InvokeArgs_t>(): 5622 case id<Invoke_t>():
5627 return traversal::Return; 5623 case id<InvokeArgs_t>():
5628 } 5624 return traversal::Return;
5625 }
5629 return traversal::Continue; 5626 return traversal::Continue;
5630 }); 5627 });
5631 } 5628 }
@@ -5781,7 +5778,7 @@ private:
5781 out.push_back(join(temp)); 5778 out.push_back(join(temp));
5782 } 5779 }
5783 5780
5784 void transformForInPlace(For_t* forNode, str_list& out, ExpList_t* assignExpList = nullptr) { 5781 void transformForInPlace(For_t* forNode, str_list& out, ExpList_t* assignExpList = nullptr) {
5785 auto x = forNode; 5782 auto x = forNode;
5786 str_list temp; 5783 str_list temp;
5787 if (assignExpList) { 5784 if (assignExpList) {
@@ -5807,11 +5804,7 @@ private:
5807 } 5804 }
5808 5805
5809 void checkOperatorAvailable(const std::string& op, ast_node* node) { 5806 void checkOperatorAvailable(const std::string& op, ast_node* node) {
5810 if (op == "&"sv || 5807 if (op == "&"sv || op == "~"sv || op == "|"sv || op == ">>"sv || op == "<<"sv) {
5811 op == "~"sv ||
5812 op == "|"sv ||
5813 op == ">>"sv ||
5814 op == "<<"sv) {
5815 if (getLuaTarget(node) < 503) { 5808 if (getLuaTarget(node) < 503) {
5816 throw std::logic_error(_info.errorMessage("bitwise operator is not available when not targeting Lua version 5.3 or higher"sv, node)); 5809 throw std::logic_error(_info.errorMessage("bitwise operator is not available when not targeting Lua version 5.3 or higher"sv, node));
5817 } 5810 }
@@ -5874,7 +5867,7 @@ private:
5874 out.push_back(join(temp)); 5867 out.push_back(join(temp));
5875 } 5868 }
5876 5869
5877 void transformForEachInPlace(ForEach_t* forEach, str_list& out, ExpList_t* assignExpList = nullptr) { 5870 void transformForEachInPlace(ForEach_t* forEach, str_list& out, ExpList_t* assignExpList = nullptr) {
5878 auto x = forEach; 5871 auto x = forEach;
5879 str_list temp; 5872 str_list temp;
5880 if (assignExpList) { 5873 if (assignExpList) {
@@ -5929,10 +5922,12 @@ private:
5929 transformDoubleString(static_cast<DoubleString_t*>(key), temp); 5922 transformDoubleString(static_cast<DoubleString_t*>(key), temp);
5930 temp.back() = '[' + temp.back() + ']'; 5923 temp.back() = '[' + temp.back() + ']';
5931 break; 5924 break;
5932 case id<SingleString_t>(): transformSingleString(static_cast<SingleString_t*>(key), temp); 5925 case id<SingleString_t>():
5926 transformSingleString(static_cast<SingleString_t*>(key), temp);
5933 temp.back() = '[' + temp.back() + ']'; 5927 temp.back() = '[' + temp.back() + ']';
5934 break; 5928 break;
5935 case id<LuaString_t>(): transformLuaString(static_cast<LuaString_t*>(key), temp); 5929 case id<LuaString_t>():
5930 transformLuaString(static_cast<LuaString_t*>(key), temp);
5936 temp.back() = "[ "s + temp.back() + ']'; 5931 temp.back() = "[ "s + temp.back() + ']';
5937 break; 5932 break;
5938 default: YUEE("AST node mismatch", key); break; 5933 default: YUEE("AST node mismatch", key); break;
@@ -6012,7 +6007,7 @@ private:
6012 } 6007 }
6013 } 6008 }
6014 6009
6015 std::pair<std::string,bool> defineClassVariable(Assignable_t* assignable) { 6010 std::pair<std::string, bool> defineClassVariable(Assignable_t* assignable) {
6016 if (auto variable = assignable->item.as<Variable_t>()) { 6011 if (auto variable = assignable->item.as<Variable_t>()) {
6017 auto name = _parser.toString(variable); 6012 auto name = _parser.toString(variable);
6018 if (addToScope(name)) { 6013 if (addToScope(name)) {
@@ -6150,7 +6145,8 @@ private:
6150 case id<class_member_list_t>(): { 6145 case id<class_member_list_t>(): {
6151 size_t inc = transform_class_member_list(static_cast<class_member_list_t*>(content), members, classVar); 6146 size_t inc = transform_class_member_list(static_cast<class_member_list_t*>(content), members, classVar);
6152 auto it = members.end(); 6147 auto it = members.end();
6153 for (size_t i = 0; i < inc; ++i, --it); 6148 for (size_t i = 0; i < inc; ++i, --it)
6149 ;
6154 for (; it != members.end(); ++it) { 6150 for (; it != members.end(); ++it) {
6155 auto& member = *it; 6151 auto& member = *it;
6156 if (member.type == MemType::Property) { 6152 if (member.type == MemType::Property) {
@@ -6164,7 +6160,7 @@ private:
6164 case id<Statement_t>(): 6160 case id<Statement_t>():
6165 transformStatement(static_cast<Statement_t*>(content), statements); 6161 transformStatement(static_cast<Statement_t*>(content), statements);
6166 break; 6162 break;
6167 default:YUEE("AST node mismatch", content); break; 6163 default: YUEE("AST node mismatch", content); break;
6168 } 6164 }
6169 } 6165 }
6170 for (auto& member : members) { 6166 for (auto& member : members) {
@@ -6667,9 +6663,7 @@ private:
6667 } 6663 }
6668 for (auto _exp : expList->exprs.objects()) { 6664 for (auto _exp : expList->exprs.objects()) {
6669 auto exp = static_cast<Exp_t*>(_exp); 6665 auto exp = static_cast<Exp_t*>(_exp);
6670 if (!variableFrom(exp) && 6666 if (!variableFrom(exp) && !exp->getByPath<unary_exp_t, Value_t, SimpleValue_t, TableLit_t>() && !exp->getByPath<unary_exp_t, Value_t, simple_table_t>()) {
6671 !exp->getByPath<unary_exp_t, Value_t, SimpleValue_t, TableLit_t>() &&
6672 !exp->getByPath<unary_exp_t, Value_t, simple_table_t>()) {
6673 throw std::logic_error(_info.errorMessage("left hand expressions must be variables in export statement"sv, x)); 6667 throw std::logic_error(_info.errorMessage("left hand expressions must be variables in export statement"sv, x));
6674 } 6668 }
6675 } 6669 }
@@ -7068,7 +7062,7 @@ private:
7068 if (ast_is<import_all_macro_t, ImportTabLit_t>(import->target)) { 7062 if (ast_is<import_all_macro_t, ImportTabLit_t>(import->target)) {
7069 x = import->target.get(); 7063 x = import->target.get();
7070 bool importAllMacro = import->target.is<import_all_macro_t>(); 7064 bool importAllMacro = import->target.is<import_all_macro_t>();
7071 std::list<std::pair<std::string,std::string>> macroPairs; 7065 std::list<std::pair<std::string, std::string>> macroPairs;
7072 auto newTab = x->new_ptr<ImportTabLit_t>(); 7066 auto newTab = x->new_ptr<ImportTabLit_t>();
7073 if (auto tabLit = import->target.as<ImportTabLit_t>()) { 7067 if (auto tabLit = import->target.as<ImportTabLit_t>()) {
7074 for (auto item : tabLit->items.objects()) { 7068 for (auto item : tabLit->items.objects()) {
@@ -7369,8 +7363,7 @@ private:
7369 for (auto branch_ : branches) { 7363 for (auto branch_ : branches) {
7370 auto branch = static_cast<SwitchCase_t*>(branch_); 7364 auto branch = static_cast<SwitchCase_t*>(branch_);
7371 if (auto value = singleValueFrom(branch->valueList); 7365 if (auto value = singleValueFrom(branch->valueList);
7372 value && (value->item.is<simple_table_t>() || 7366 value && (value->item.is<simple_table_t>() || value->getByPath<SimpleValue_t, TableLit_t>())) {
7373 value->getByPath<SimpleValue_t, TableLit_t>())) {
7374 if (!firstBranch) { 7367 if (!firstBranch) {
7375 temp.push_back(indent() + "else"s + nll(branch)); 7368 temp.push_back(indent() + "else"s + nll(branch));
7376 pushScope(); 7369 pushScope();
@@ -7440,8 +7433,7 @@ private:
7440 if (!singleValueFrom(exp)) { 7433 if (!singleValueFrom(exp)) {
7441 tmp.back() = '(' + tmp.back() + ')'; 7434 tmp.back() = '(' + tmp.back() + ')';
7442 } 7435 }
7443 temp.back().append(' ' + tmp.back() + " == "s + 7436 temp.back().append(' ' + tmp.back() + " == "s + (exp == exprs.back() ? objVar : objVar + " or"s));
7444 (exp == exprs.back() ? objVar : objVar + " or"s));
7445 } 7437 }
7446 temp.back().append(" then"s + nll(branch)); 7438 temp.back().append(" then"s + nll(branch));
7447 pushScope(); 7439 pushScope();
@@ -7674,22 +7666,23 @@ const std::string YueCompilerImpl::Empty;
7674 7666
7675YueCompiler::YueCompiler(void* sharedState, 7667YueCompiler::YueCompiler(void* sharedState,
7676 const std::function<void(void*)>& luaOpen, 7668 const std::function<void(void*)>& luaOpen,
7677 bool sameModule): 7669 bool sameModule)
7670 :
7678#ifndef YUE_NO_MACRO 7671#ifndef YUE_NO_MACRO
7679_compiler(std::make_unique<YueCompilerImpl>(static_cast<lua_State*>(sharedState), luaOpen, sameModule)) {} 7672 _compiler(std::make_unique<YueCompilerImpl>(static_cast<lua_State*>(sharedState), luaOpen, sameModule)) {
7673}
7680#else 7674#else
7681_compiler(std::make_unique<YueCompilerImpl>()) { 7675 _compiler(std::make_unique<YueCompilerImpl>()) {
7682 (void)sharedState; 7676 (void)sharedState;
7683 (void)luaOpen; 7677 (void)luaOpen;
7684 (void)sameModule; 7678 (void)sameModule;
7685} 7679}
7686#endif // YUE_NO_MACRO 7680#endif // YUE_NO_MACRO
7687 7681
7688YueCompiler::~YueCompiler() {} 7682YueCompiler::~YueCompiler() { }
7689 7683
7690CompileInfo YueCompiler::compile(std::string_view codes, const YueConfig& config) { 7684CompileInfo YueCompiler::compile(std::string_view codes, const YueConfig& config) {
7691 return _compiler->compile(codes, config); 7685 return _compiler->compile(codes, config);
7692} 7686}
7693 7687
7694} // namespace yue 7688} // namespace yue
7695
diff --git a/src/yuescript/yue_compiler.h b/src/yuescript/yue_compiler.h
index 3df5451..9ca641a 100644
--- a/src/yuescript/yue_compiler.h
+++ b/src/yuescript/yue_compiler.h
@@ -8,14 +8,14 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
8 8
9#pragma once 9#pragma once
10 10
11#include <functional>
12#include <list>
13#include <memory>
11#include <string> 14#include <string>
12#include <string_view> 15#include <string_view>
13#include <tuple> 16#include <tuple>
14#include <list>
15#include <vector>
16#include <memory>
17#include <unordered_map> 17#include <unordered_map>
18#include <functional> 18#include <vector>
19 19
20namespace yue { 20namespace yue {
21 21
@@ -59,6 +59,7 @@ public:
59 bool sameModule = false); 59 bool sameModule = false);
60 virtual ~YueCompiler(); 60 virtual ~YueCompiler();
61 CompileInfo compile(std::string_view codes, const YueConfig& config = {}); 61 CompileInfo compile(std::string_view codes, const YueConfig& config = {});
62
62private: 63private:
63 std::unique_ptr<YueCompilerImpl> _compiler; 64 std::unique_ptr<YueCompilerImpl> _compiler;
64}; 65};
diff --git a/src/yuescript/yue_parser.cpp b/src/yuescript/yue_parser.cpp
index 31a2560..a22bd3a 100755
--- a/src/yuescript/yue_parser.cpp
+++ b/src/yuescript/yue_parser.cpp
@@ -17,8 +17,7 @@ std::unordered_set<std::string> LuaKeywords = {
17 "end"s, "false"s, "for"s, "function"s, "goto"s, 17 "end"s, "false"s, "for"s, "function"s, "goto"s,
18 "if"s, "in"s, "local"s, "nil"s, "not"s, 18 "if"s, "in"s, "local"s, "nil"s, "not"s,
19 "or"s, "repeat"s, "return"s, "then"s, "true"s, 19 "or"s, "repeat"s, "return"s, "then"s, "true"s,
20 "until"s, "while"s 20 "until"s, "while"s};
21};
22 21
23std::unordered_set<std::string> Keywords = { 22std::unordered_set<std::string> Keywords = {
24 "and"s, "break"s, "do"s, "else"s, "elseif"s, 23 "and"s, "break"s, "do"s, "else"s, "elseif"s,
@@ -31,6 +30,7 @@ std::unordered_set<std::string> Keywords = {
31 "try"s, "unless"s, "using"s, "when"s, "with"s // Yue keywords 30 "try"s, "unless"s, "using"s, "when"s, "with"s // Yue keywords
32}; 31};
33 32
33// clang-format off
34YueParser::YueParser() { 34YueParser::YueParser() {
35 plain_space = *set(" \t"); 35 plain_space = *set(" \t");
36 Break = nl(-expr('\r') >> '\n'); 36 Break = nl(-expr('\r') >> '\n');
@@ -55,14 +55,14 @@ YueParser::YueParser() {
55 +(range('0', '9') | range('a', 'f') | range('A', 'F')) >> 55 +(range('0', '9') | range('a', 'f') | range('A', 'F')) >>
56 -(-set("uU") >> set("lL") >> set("lL")) 56 -(-set("uU") >> set("lL") >> set("lL"))
57 ) | ( 57 ) | (
58 +range('0', '9') >> -set("uU") >> set("lL") >> set("lL") 58 +range('0', '9') >> (
59 ) | ( 59 '.' >> +range('0', '9') >> -(set("eE") >> -expr('-') >> +range('0', '9')) |
60 ( 60 -set("uU") >> set("lL") >> set("lL") |
61 +range('0', '9') >> -('.' >> +range('0', '9')) 61 true_()
62 ) | (
63 '.' >> +range('0', '9')
64 ) 62 )
65 ) >> -(set("eE") >> -expr('-') >> +range('0', '9')); 63 ) | (
64 '.' >> +range('0', '9') >> -(set("eE") >> -expr('-') >> +range('0', '9'))
65 );
66 66
67 Cut = false_(); 67 Cut = false_();
68 Seperator = true_(); 68 Seperator = true_();
@@ -652,6 +652,7 @@ YueParser::YueParser() {
652 BlockEnd = Block >> -(+Break >> Space >> and_(Stop)) >> Stop; 652 BlockEnd = Block >> -(+Break >> Space >> and_(Stop)) >> Stop;
653 File = White >> -Shebang >> -Block >> White >> eof(); 653 File = White >> -Shebang >> -Block >> White >> eof();
654} 654}
655// clang-format on
655 656
656ParseInfo YueParser::parse(std::string_view codes, rule& r) { 657ParseInfo YueParser::parse(std::string_view codes, rule& r) {
657 ParseInfo res; 658 ParseInfo res;
@@ -710,20 +711,20 @@ std::string YueParser::decode(const input& codes) {
710} 711}
711 712
712namespace Utils { 713namespace Utils {
713 void replace(std::string& str, std::string_view from, std::string_view to) { 714void replace(std::string& str, std::string_view from, std::string_view to) {
714 size_t start_pos = 0; 715 size_t start_pos = 0;
715 while((start_pos = str.find(from, start_pos)) != std::string::npos) { 716 while ((start_pos = str.find(from, start_pos)) != std::string::npos) {
716 str.replace(start_pos, from.size(), to); 717 str.replace(start_pos, from.size(), to);
717 start_pos += to.size(); 718 start_pos += to.size();
718 }
719 } 719 }
720}
720 721
721 void trim(std::string& str) { 722void trim(std::string& str) {
722 if (str.empty()) return; 723 if (str.empty()) return;
723 str.erase(0, str.find_first_not_of(" \t\r\n")); 724 str.erase(0, str.find_first_not_of(" \t\r\n"));
724 str.erase(str.find_last_not_of(" \t\r\n") + 1); 725 str.erase(str.find_last_not_of(" \t\r\n") + 1);
725 }
726} 726}
727} // namespace Utils
727 728
728std::string ParseInfo::errorMessage(std::string_view msg, const input_range* loc) const { 729std::string ParseInfo::errorMessage(std::string_view msg, const input_range* loc) const {
729 const int ASCII = 255; 730 const int ASCII = 255;
@@ -753,13 +754,14 @@ std::string ParseInfo::errorMessage(std::string_view msg, const input_range* loc
753 } 754 }
754 auto line = Converter{}.to_bytes(std::wstring(begin, end)); 755 auto line = Converter{}.to_bytes(std::wstring(begin, end));
755 while (col < static_cast<int>(line.size()) 756 while (col < static_cast<int>(line.size())
756 && (line[col] == ' ' || line[col] == '\t')) { 757 && (line[col] == ' ' || line[col] == '\t')) {
757 col++; 758 col++;
758 } 759 }
759 Utils::replace(line, "\t"sv, " "sv); 760 Utils::replace(line, "\t"sv, " "sv);
760 std::ostringstream buf; 761 std::ostringstream buf;
761 buf << loc->m_begin.m_line << ": "sv << msg << 762 buf << loc->m_begin.m_line << ": "sv << msg << '\n'
762 '\n' << line << '\n' << std::string(col, ' ') << "^"sv; 763 << line << '\n'
764 << std::string(col, ' ') << "^"sv;
763 return buf.str(); 765 return buf.str();
764} 766}
765 767
diff --git a/src/yuescript/yue_parser.h b/src/yuescript/yue_parser.h
index b363ad7..3ee219e 100755
--- a/src/yuescript/yue_parser.h
+++ b/src/yuescript/yue_parser.h
@@ -8,14 +8,14 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
8 8
9#pragma once 9#pragma once
10 10
11#include <string>
12#include <unordered_set>
13#include <stack>
14#include <algorithm> 11#include <algorithm>
15#include <list> 12#include <list>
13#include <memory>
16#include <sstream> 14#include <sstream>
15#include <stack>
16#include <string>
17#include <string_view> 17#include <string_view>
18#include <memory> 18#include <unordered_set>
19 19
20#include "yuescript/ast.hpp" 20#include "yuescript/ast.hpp"
21#include "yuescript/yue_ast.h" 21#include "yuescript/yue_ast.h"
@@ -35,7 +35,7 @@ struct ParseInfo {
35 std::string errorMessage(std::string_view msg, const input_range* loc) const; 35 std::string errorMessage(std::string_view msg, const input_range* loc) const;
36}; 36};
37 37
38template<typename T> 38template <typename T>
39struct identity { typedef T type; }; 39struct identity { typedef T type; };
40 40
41#define AST_RULE(type) \ 41#define AST_RULE(type) \
@@ -50,7 +50,7 @@ class YueParser {
50public: 50public:
51 YueParser(); 51 YueParser();
52 52
53 template<class AST> 53 template <class AST>
54 ParseInfo parse(std::string_view codes) { 54 ParseInfo parse(std::string_view codes) {
55 return parse(codes, getRule<AST>()); 55 return parse(codes, getRule<AST>());
56 } 56 }
@@ -338,8 +338,8 @@ private:
338}; 338};
339 339
340namespace Utils { 340namespace Utils {
341 void replace(std::string& str, std::string_view from, std::string_view to); 341void replace(std::string& str, std::string_view from, std::string_view to);
342 void trim(std::string& str); 342void trim(std::string& str);
343}; 343} // namespace Utils
344 344
345} // namespace yue 345} // namespace yue
diff --git a/src/yuescript/yuescript.cpp b/src/yuescript/yuescript.cpp
index 98e214f..08978e5 100644
--- a/src/yuescript/yuescript.cpp
+++ b/src/yuescript/yuescript.cpp
@@ -19,11 +19,12 @@ using namespace std::string_literals;
19 19
20extern "C" { 20extern "C" {
21 21
22#include "lua.h"
23#include "lauxlib.h" 22#include "lauxlib.h"
23#include "lua.h"
24 24
25static const char yuescriptCodes[] = 25static const char yuescriptCodes[] =
26#include "yuescript/yuescript.h" 26#include "yuescript/yuescript.h"
27 ;
27 28
28static void init_yuescript(lua_State* L) { 29static void init_yuescript(lua_State* L) {
29 if (luaL_loadbuffer(L, yuescriptCodes, sizeof(yuescriptCodes) / sizeof(yuescriptCodes[0]) - 1, "=(yuescript)") != 0) { 30 if (luaL_loadbuffer(L, yuescriptCodes, sizeof(yuescriptCodes) / sizeof(yuescriptCodes[0]) - 1, "=(yuescript)") != 0) {
@@ -40,6 +41,7 @@ static void init_yuescript(lua_State* L) {
40 41
41static const char stpCodes[] = 42static const char stpCodes[] =
42#include "yuescript/stacktraceplus.h" 43#include "yuescript/stacktraceplus.h"
44 ;
43 45
44static int init_stacktraceplus(lua_State* L) { 46static int init_stacktraceplus(lua_State* L) {
45 if (luaL_loadbuffer(L, stpCodes, sizeof(stpCodes) / sizeof(stpCodes[0]) - 1, "=(stacktraceplus)") != 0) { 47 if (luaL_loadbuffer(L, stpCodes, sizeof(stpCodes) / sizeof(stpCodes[0]) - 1, "=(stacktraceplus)") != 0) {
@@ -218,8 +220,7 @@ static const luaL_Reg yuelib[] = {
218 {"version", nullptr}, 220 {"version", nullptr},
219 {"options", nullptr}, 221 {"options", nullptr},
220 {"load_stacktraceplus", nullptr}, 222 {"load_stacktraceplus", nullptr},
221 {nullptr, nullptr} 223 {nullptr, nullptr}};
222};
223 224
224YUE_API int luaopen_yue(lua_State* L) { 225YUE_API int luaopen_yue(lua_State* L) {
225#if LUA_VERSION_NUM > 501 226#if LUA_VERSION_NUM > 501
@@ -243,4 +244,3 @@ YUE_API int luaopen_yue(lua_State* L) {
243} 244}
244 245
245} // extern "C" 246} // extern "C"
246