From 52a6536103f46c26a3ba9b149b0fe7b40d524d8c Mon Sep 17 00:00:00 2001 From: Li Jin Date: Fri, 10 Jan 2020 16:30:34 +0800 Subject: update. --- MoonParser/ast.cpp | 122 -- MoonParser/ast.hpp | 575 ------- MoonParser/moon_ast.cpp | 105 -- MoonParser/moon_ast.h | 581 ------- MoonParser/moon_compiler.cpp | 3851 ------------------------------------------ MoonParser/moon_compiler.h | 18 - MoonParser/moon_parser.cpp | 513 ------ MoonParser/moon_parser.h | 27 - MoonParser/moonc.cpp | 21 - MoonParser/parser.cpp | 1430 ---------------- MoonParser/parser.hpp | 425 ----- 11 files changed, 7668 deletions(-) delete mode 100644 MoonParser/ast.cpp delete mode 100644 MoonParser/ast.hpp delete mode 100644 MoonParser/moon_ast.cpp delete mode 100644 MoonParser/moon_ast.h delete mode 100644 MoonParser/moon_compiler.cpp delete mode 100644 MoonParser/moon_compiler.h delete mode 100644 MoonParser/moon_parser.cpp delete mode 100644 MoonParser/moon_parser.h delete mode 100644 MoonParser/moonc.cpp delete mode 100644 MoonParser/parser.cpp delete mode 100644 MoonParser/parser.hpp (limited to 'MoonParser') diff --git a/MoonParser/ast.cpp b/MoonParser/ast.cpp deleted file mode 100644 index 6c86854..0000000 --- a/MoonParser/ast.cpp +++ /dev/null @@ -1,122 +0,0 @@ -#include -#include "ast.hpp" - - -namespace parserlib { - -int ast_type_id = 0; - -traversal ast_node::traverse(const std::function& func) { - return func(this); -} - -ast_node* ast_node::getByTypeIds(int* begin, int* end) { - ast_node* current = this; - auto it = begin; - while (it != end) { - ast_node* findNode = nullptr; - int type = *it; - current->visitChild([&](ast_node* node) { - if (node->get_type() == type) { - findNode = node; - return true; - } - return false; - }); - if (findNode) { - current = findNode; - } else { - current = nullptr; - break; - } - ++it; - } - return current; -} - -bool ast_node::visitChild(const std::function&) { - return false; -} - - -/** Asks all members to construct themselves from the stack. - The members are asked to construct themselves in reverse order. - from a node stack. - @param st stack. - */ -void ast_container::construct(ast_stack &st) { - for(ast_member_vector::reverse_iterator it = m_members.rbegin(); - it != m_members.rend(); - ++it) - { - ast_member* member = *it; - member->construct(st); - } -} - -traversal ast_container::traverse(const std::function& func) { - traversal action = func(this); - switch (action) { - case traversal::Stop: return traversal::Stop; - case traversal::Return: return traversal::Continue; - default: break; - } - const auto& members = this->members(); - for (auto member : members) { - if (_ast_ptr* ptr = ast_cast<_ast_ptr>(member)) { - if (ptr->get() && ptr->get()->traverse(func) == traversal::Stop) { - return traversal::Stop; - } - } else if (_ast_list* list = ast_cast<_ast_list>(member)) { - for (auto obj : list->objects()) { - if (obj->traverse(func) == traversal::Stop) { - return traversal::Stop; - } - } - } - } - return traversal::Continue; -} - -bool ast_container::visitChild(const std::function& func) { - const auto& members = this->members(); - for (auto member : members) { - if (_ast_ptr* ptr = ast_cast<_ast_ptr>(member)) { - if (ptr->get()) { - if (func(ptr->get())) return true; - } - } else if (_ast_list* list = ast_cast<_ast_list>(member)) { - for (auto obj : list->objects()) { - if (obj) { - if (func(obj)) return true; - } - } - } - } - return false; -} - - -/** parses the given input. - @param i input. - @param g root rule of grammar. - @param el list of errors. - @param ud user data, passed to the parse procedures. - @return pointer to ast node created, or null if there was an error. - The return object must be deleted by the caller. - */ -ast_node* _parse(input &i, rule &g, error_list &el, void* ud) { - ast_stack st; - if (!parse(i, g, el, &st, ud)) { - for (auto node : st) { - delete node; - } - st.clear(); - return nullptr; - } - assert(st.size() == 1); - return st.front(); -} - - -} //namespace parserlib diff --git a/MoonParser/ast.hpp b/MoonParser/ast.hpp deleted file mode 100644 index b388e77..0000000 --- a/MoonParser/ast.hpp +++ /dev/null @@ -1,575 +0,0 @@ -#pragma once - - -#include -#include -#include -#include -#include "parser.hpp" - - -namespace parserlib { - - -class ast_node; -template class ast_ptr; -template class ast_list; -template class ast; - - -/** type of AST node stack. - */ -typedef std::vector ast_stack; -typedef std::list node_container; - -extern int ast_type_id; - -template -int ast_type() { - static int type = ast_type_id++; - return type; -} - -enum class traversal { - Continue, - Return, - Stop -}; - -/** Base class for AST nodes. - */ -class ast_node : public input_range { -public: - ast_node() : _ref(0) {} - - void retain() { - ++_ref; - } - - void release() { - --_ref; - if (_ref == 0) { - delete this; - } - } - - /** interface for filling the contents of the node - from a node stack. - @param st stack. - */ - virtual void construct(ast_stack& st) {} - - /** interface for visiting AST tree use. - */ - virtual traversal traverse(const std::function& func); - - template - struct select_last { - using type = typename decltype((std::enable_if{}, ...))::type; - }; - template - using select_last_t = typename select_last::type; - - template - select_last_t* getByPath() { - int types[] = {ast_type()...}; - return static_cast*>(getByTypeIds(std::begin(types), std::end(types))); - } - - virtual bool visitChild(const std::function& func); - - virtual size_t getId() const { return "ast_node"_id; } - - virtual const char* getName() const { return "ast_node"; } - - virtual int get_type() { return ast_type(); } - - template - inline ast_ptr new_ptr() { - auto item = new T; - item->m_begin.m_line = m_begin.m_line; - item->m_end.m_line = m_begin.m_line; - return ast_ptr(item); - } -private: - int _ref; - ast_node* getByTypeIds(int* begin, int* end); -}; - -template -T* ast_cast(ast_node* node) { - return node && ast_type() == node->get_type() ? static_cast(node) : nullptr; -} - -template -T* ast_to(ast_node* node) { - assert(node->get_type() == ast_type()); - return static_cast(node); -} - -template -bool ast_is(ast_node* node) { - if (!node) return false; - bool result = false; - int type = node->get_type(); - using swallow = bool[]; - (void)swallow{result || (result = ast_type() == type)...}; - return result; -} - -class ast_member; - -/** type of ast member vector. - */ -typedef std::vector ast_member_vector; - - -/** base class for AST nodes with children. - */ -class ast_container : public ast_node { -public: - void add_members(std::initializer_list members) { - for (auto member : members) { - m_members.push_back(member); - } - } - - /** returns the vector of AST members. - @return the vector of AST members. - */ - const ast_member_vector& members() const { - return m_members; - } - - /** Asks all members to construct themselves from the stack. - The members are asked to construct themselves in reverse order. - from a node stack. - @param st stack. - */ - virtual void construct(ast_stack& st) override; - - virtual traversal traverse(const std::function& func) override; - - virtual bool visitChild(const std::function& func) override; - - virtual size_t getId() const override { return "ast_container"_id; } - - virtual const char* getName() const override { return "ast_container"; } -private: - ast_member_vector m_members; - - friend class ast_member; -}; - - -/** Base class for children of ast_container. - */ -class ast_member { -public: - virtual ~ast_member() {} - - /** interface for filling the the member from a node stack. - @param st stack. - */ - virtual void construct(ast_stack& st) = 0; - - virtual bool accept(ast_node* node) = 0; - - virtual int get_type() { return ast_type(); } -}; - -template -T* ast_cast(ast_member* member) { - return member && ast_type() == member->get_type() ? static_cast(member) : nullptr; -} - -class _ast_ptr : public ast_member { -public: - _ast_ptr(ast_node* node) : m_ptr(node) { - if (node) node->retain(); - } - - virtual ~_ast_ptr() { - if (m_ptr) { - m_ptr->release(); - m_ptr = nullptr; - } - } - - ast_node* get() const { - return m_ptr; - } - - template - T* as() const { - return ast_cast(m_ptr); - } - - template - T* to() const { - assert(m_ptr && m_ptr->get_type() == ast_type()); - return static_cast(m_ptr); - } - - template - bool is() const { - return m_ptr && m_ptr->get_type() == ast_type(); - } - - void set(ast_node* node) { - if (node == m_ptr) { - return; - } else if (!node) { - if (m_ptr) m_ptr->release(); - m_ptr = nullptr; - } else { - assert(accept(node)); - if (m_ptr) m_ptr->release(); - m_ptr = node; - node->retain(); - } - } - - virtual int get_type() override { - return ast_type<_ast_ptr>(); - } -protected: - ast_node* m_ptr; -}; - -/** pointer to an AST object. - It assumes ownership of the object. - It pops an object of the given type from the stack. - @tparam Required if true, the object is required. - @tparam T type of object to control. - */ -template class ast_ptr : public _ast_ptr { -public: - ast_ptr(T* node = nullptr) : _ast_ptr(node) {} - - ast_ptr(const ast_ptr& other) : _ast_ptr(other.get()) {} - - ast_ptr& operator=(const ast_ptr& other) { - set(other.get()); - return *this; - } - - /** gets the underlying ptr value. - @return the underlying ptr value. - */ - T* get() const { - return static_cast(m_ptr); - } - - /** auto conversion to the underlying object ptr. - @return the underlying ptr value. - */ - operator T*() const { - return static_cast(m_ptr); - } - - /** member access. - @return the underlying ptr value. - */ - T* operator->() const { - assert(m_ptr); - return static_cast(m_ptr); - } - - /** Pops a node from the stack. - @param st stack. - @exception std::logic_error thrown if the node is not of the appropriate type; - thrown only if Required == true or if the stack is empty. - */ - virtual void construct(ast_stack& st) override { - // check the stack node - if (st.empty()) { - if (!Required) return; - throw std::logic_error("Invalid AST stack"); - } - ast_node* node = st.back(); - if (!ast_ptr::accept(node)) { - // if the object is not required, simply return - if (!Required) return; - // else if the object is mandatory, throw an exception - throw std::logic_error("Invalid AST node"); - } - st.pop_back(); - m_ptr = node; - node->retain(); - } -private: - virtual bool accept(ast_node* node) override { - return node && (std::is_same() || ast_type() == node->get_type()); - } -}; - -template class ast_sel : public _ast_ptr { -public: - ast_sel() : _ast_ptr(nullptr) {} - - ast_sel(const ast_sel& other) : _ast_ptr(other.get()) {} - - ast_sel& operator=(const ast_sel& other) { - set(other.get()); - return *this; - } - - operator ast_node*() const { - return m_ptr; - } - - ast_node* operator->() const { - assert(m_ptr); - return m_ptr; - } - - virtual void construct(ast_stack& st) override { - if (st.empty()) { - if (!Required) return; - throw std::logic_error("Invalid AST stack"); - } - ast_node* node = st.back(); - if (!ast_sel::accept(node)) { - if (!Required) return; - throw std::logic_error("Invalid AST node"); - } - st.pop_back(); - m_ptr = node; - node->retain(); - } -private: - virtual bool accept(ast_node* node) override { - if (!node) return false; - using swallow = bool[]; - bool result = false; - (void)swallow{result || (result = ast_type() == node->get_type())...}; - return result; - } -}; - -class _ast_list : public ast_member { -public: - ~_ast_list() { - clear(); - } - - inline ast_node* back() const { - return m_objects.back(); - } - - inline ast_node* front() const { - return m_objects.front(); - } - - inline size_t size() const { - return m_objects.size(); - } - - inline bool empty() const { - return m_objects.empty(); - } - - void push_back(ast_node* node) { - assert(node && accept(node)); - m_objects.push_back(node); - node->retain(); - } - - void push_front(ast_node* node) { - assert(node && accept(node)); - m_objects.push_front(node); - node->retain(); - } - - void pop_front() { - auto node = m_objects.front(); - m_objects.pop_front(); - node->release(); - } - - void set_front(ast_node* node) { - assert(node && accept(node)); - m_objects.front()->release(); - m_objects.front() = node; - node->retain(); - } - - void set_back(ast_node* node) { - assert(node && accept(node)); - m_objects.back()->release(); - m_objects.back() = node; - node->retain(); - } - - const node_container& objects() const { - return m_objects; - } - - void clear() { - for(ast_node* obj : m_objects) { - if (obj) obj->release(); - } - m_objects.clear(); - } - - void dup(const _ast_list& src) { - for(ast_node* obj : src.m_objects) { - m_objects.push_back(obj); - obj->retain(); - } - } - - virtual int get_type() override { return ast_type<_ast_list>(); } -protected: - node_container m_objects; -}; - -/** A list of objects. - It pops objects of the given type from the ast stack, until no more objects can be popped. - It assumes ownership of objects. - @tparam Required if true, the object is required. - @tparam T type of object to control. - */ -template class ast_list : public _ast_list { -public: - ast_list() { } - - ast_list(const ast_list& other) { - dup(other); - } - - ast_list& operator=(const ast_list& other) { - clear(); - dup(other); - return *this; - } - - /** Pops objects of type T from the stack until no more objects can be popped. - @param st stack. - */ - virtual void construct(ast_stack &st) override { - while (!st.empty()) { - ast_node* node = st.back(); - // if the object was not not of the appropriate type, - // end the list parsing - if (!ast_list::accept(node)) { - if (Required && m_objects.empty()) { - throw std::logic_error("Invalid AST node"); - } - return; - } - st.pop_back(); - // insert the object in the list, in reverse order - m_objects.push_front(node); - node->retain(); - } - if (Required && m_objects.empty()) { - throw std::logic_error("Invalid AST stack"); - } - } -private: - virtual bool accept(ast_node* node) override { - return node && (std::is_same() || ast_type() == node->get_type()); - } -}; - -template class ast_sel_list : public _ast_list { -public: - ast_sel_list() { } - - ast_sel_list(const ast_sel_list& other) { - dup(other); - } - - ast_sel_list& operator=(const ast_sel_list& other) { - clear(); - dup(other); - return *this; - } - - virtual void construct(ast_stack &st) override { - while (!st.empty()) { - ast_node* node = st.back(); - if (!ast_sel_list::accept(node)) { - if (Required && m_objects.empty()) { - throw std::logic_error("Invalid AST node"); - } - return; - } - st.pop_back(); - m_objects.push_front(node); - node->retain(); - } - if (Required && m_objects.empty()) { - throw std::logic_error("Invalid AST stack"); - } - } -private: - virtual bool accept(ast_node* node) override { - if (!node) return false; - using swallow = bool[]; - bool result = false; - (void)swallow{result || (result = ast_type() == node->get_type())...}; - return result; - } -}; - -/** AST function which creates an object of type T - and pushes it to the node stack. - */ -template class ast { -public: - /** constructor. - @param r rule to attach the AST function to. - */ - ast(rule& r) { - r.set_parse_proc(&_parse_proc); - } - -private: - //parse proc - static void _parse_proc(const pos& b, const pos& e, void* d) { - ast_stack* st = reinterpret_cast(d); - T* obj = new T; - obj->m_begin = b; - obj->m_end = e; - obj->construct(*st); - st->push_back(obj); - } -}; - - -/** parses the given input. - @param i input. - @param g root rule of grammar. - @param el list of errors. - @param ud user data, passed to the parse procedures. - @return pointer to ast node created, or null if there was an error. - The return object must be deleted by the caller. - */ -ast_node* _parse(input &i, rule &g, error_list &el, void* ud); - - -/** parses the given input. - @param i input. - @param g root rule of grammar. - @param el list of errors. - @param ud user data, passed to the parse procedures. - @return ast nodes. - */ -template ast_ptr parse(input &i, rule &g, error_list &el, void* ud = nullptr) { - ast_node* node = _parse(i, g, el, ud); - T* ast = ast_cast(node); - ast_ptr ptr; - if (ast) { - ast_stack st{node}; - ptr.construct(st); - } else if (node) { - delete node; - } - return ptr; -} - - -} //namespace parserlib diff --git a/MoonParser/moon_ast.cpp b/MoonParser/moon_ast.cpp deleted file mode 100644 index 6b175fc..0000000 --- a/MoonParser/moon_ast.cpp +++ /dev/null @@ -1,105 +0,0 @@ -#include "moon_ast.h" - -namespace MoonP { - -#define AST_IMPL(type) \ - ast __##type##_t(type); - -AST_IMPL(Num) -AST_IMPL(Name) -AST_IMPL(Variable) -AST_IMPL(LuaKeyword) -AST_IMPL(self) -AST_IMPL(self_name) -AST_IMPL(self_class) -AST_IMPL(self_class_name) -AST_IMPL(SelfName) -AST_IMPL(KeyName) -AST_IMPL(VarArg) -AST_IMPL(local_flag) -AST_IMPL(Seperator) -AST_IMPL(NameList) -AST_IMPL(Local) -AST_IMPL(colon_import_name) -AST_IMPL(Import) -AST_IMPL(ExpListLow) -AST_IMPL(ExpList) -AST_IMPL(Return) -AST_IMPL(With) -AST_IMPL(SwitchCase) -AST_IMPL(Switch) -AST_IMPL(IfCond) -AST_IMPL(If) -AST_IMPL(Unless) -AST_IMPL(While) -AST_IMPL(for_step_value) -AST_IMPL(For) -AST_IMPL(ForEach) -AST_IMPL(Do) -AST_IMPL(Comprehension) -AST_IMPL(comp_value) -AST_IMPL(TblComprehension) -AST_IMPL(star_exp) -AST_IMPL(CompForEach) -AST_IMPL(CompFor) -AST_IMPL(CompInner) -AST_IMPL(Assign) -AST_IMPL(update_op) -AST_IMPL(Update) -AST_IMPL(BinaryOperator) -AST_IMPL(Assignable) -AST_IMPL(AssignableChain) -AST_IMPL(exp_op_value) -AST_IMPL(Exp) -AST_IMPL(Callable) -AST_IMPL(ChainValue) -AST_IMPL(simple_table) -AST_IMPL(SimpleValue) -AST_IMPL(Value) -AST_IMPL(LuaStringOpen); -AST_IMPL(LuaStringContent); -AST_IMPL(LuaStringClose); -AST_IMPL(LuaString) -AST_IMPL(SingleString) -AST_IMPL(double_string_inner) -AST_IMPL(double_string_content) -AST_IMPL(DoubleString) -AST_IMPL(String) -AST_IMPL(Parens) -AST_IMPL(DotChainItem) -AST_IMPL(ColonChainItem) -AST_IMPL(default_value) -AST_IMPL(Slice) -AST_IMPL(Invoke) -AST_IMPL(TableLit) -AST_IMPL(TableBlock) -AST_IMPL(class_member_list) -AST_IMPL(ClassBlock) -AST_IMPL(ClassDecl) -AST_IMPL(export_values) -AST_IMPL(export_op) -AST_IMPL(Export) -AST_IMPL(variable_pair) -AST_IMPL(normal_pair) -AST_IMPL(FnArgDef) -AST_IMPL(FnArgDefList) -AST_IMPL(outer_var_shadow) -AST_IMPL(FnArgsDef) -AST_IMPL(fn_arrow) -AST_IMPL(FunLit) -AST_IMPL(NameOrDestructure) -AST_IMPL(AssignableNameList) -AST_IMPL(InvokeArgs) -AST_IMPL(const_value) -AST_IMPL(unary_exp) -AST_IMPL(ExpListAssign) -AST_IMPL(if_else_line) -AST_IMPL(unless_line) -AST_IMPL(statement_appendix) -AST_IMPL(BreakLoop) -AST_IMPL(Statement) -AST_IMPL(Body) -AST_IMPL(Block) -AST_IMPL(File) - -} // namespace MoonP diff --git a/MoonParser/moon_ast.h b/MoonParser/moon_ast.h deleted file mode 100644 index a77fb40..0000000 --- a/MoonParser/moon_ast.h +++ /dev/null @@ -1,581 +0,0 @@ -#pragma once - -#include "moon_parser.h" - -namespace MoonP { - -#define AST_LEAF(type, id) \ -extern rule type; \ -class type##_t : public ast_node \ -{ \ -public: \ - virtual int get_type() override { return ast_type(); } \ - virtual size_t getId() const override { return id; } \ - virtual const char* getName() const override { return #type; } - -#define AST_NODE(type, id) \ -extern rule type; \ -class type##_t : public ast_container \ -{ \ -public: \ - virtual int get_type() override { return ast_type(); } \ - virtual size_t getId() const override { return id; } \ - virtual const char* getName() const override { return #type; } - -#define AST_MEMBER(type, ...) \ - type##_t() { \ - add_members({__VA_ARGS__}); \ - } - -#define AST_END(type) \ -}; - -AST_LEAF(Num, "Num"_id) -AST_END(Num) - -AST_LEAF(Name, "Name"_id) -AST_END(Name) - -AST_NODE(Variable, "Variable"_id) - ast_ptr name; - AST_MEMBER(Variable, &name) -AST_END(Variable) - -AST_NODE(LuaKeyword, "LuaKeyword"_id) - ast_ptr name; - AST_MEMBER(LuaKeyword, &name) -AST_END(LuaKeyword) - -AST_LEAF(self, "self"_id) -AST_END(self) - -AST_NODE(self_name, "self_name"_id) - ast_ptr name; - AST_MEMBER(self_name, &name) -AST_END(self_name) - -AST_LEAF(self_class, "self_class"_id) -AST_END(self_class) - -AST_NODE(self_class_name, "self_class_name"_id) - ast_ptr name; - AST_MEMBER(self_class_name, &name) -AST_END(self_class_name) - -AST_NODE(SelfName, "SelfName"_id) - ast_sel name; - AST_MEMBER(SelfName, &name) -AST_END(SelfName) - -AST_NODE(KeyName, "KeyName"_id) - ast_sel name; - AST_MEMBER(KeyName, &name) -AST_END(KeyName) - -AST_LEAF(VarArg, "VarArg"_id) -AST_END(VarArg) - -AST_LEAF(local_flag, "local_flag"_id) -AST_END(local_flag) - -AST_LEAF(Seperator, "Seperator"_id) -AST_END(Seperator) - -AST_NODE(NameList, "NameList"_id) - ast_ptr sep; - ast_list names; - AST_MEMBER(NameList, &sep, &names) -AST_END(NameList) - -AST_NODE(Local, "Local"_id) - ast_sel name; - std::list forceDecls; - std::list decls; - AST_MEMBER(Local, &name) -AST_END(Local) - -AST_NODE(colon_import_name, "colon_import_name"_id) - ast_ptr name; - AST_MEMBER(colon_import_name, &name) -AST_END(colon_import_name) - -class Exp_t; - -AST_NODE(Import, "Import"_id) - ast_ptr sep; - ast_sel_list names; - ast_ptr exp; - AST_MEMBER(Import, &sep, &names, &exp) -AST_END(Import) - -AST_NODE(ExpListLow, "ExpListLow"_id) - ast_ptr sep; - ast_list exprs; - AST_MEMBER(ExpListLow, &sep, &exprs) -AST_END(ExpListLow) - -AST_NODE(ExpList, "ExpList"_id) - ast_ptr sep; - ast_list exprs; - AST_MEMBER(ExpList, &sep, &exprs) -AST_END(ExpList) - -AST_NODE(Return, "Return"_id) - ast_ptr valueList; - AST_MEMBER(Return, &valueList) -AST_END(Return) - -class Assign_t; -class Body_t; - -AST_NODE(With, "With"_id) - ast_ptr valueList; - ast_ptr assigns; - ast_ptr body; - AST_MEMBER(With, &valueList, &assigns, &body) -AST_END(With) - -AST_NODE(SwitchCase, "SwitchCase"_id) - ast_ptr valueList; - ast_ptr body; - AST_MEMBER(SwitchCase, &valueList, &body) -AST_END(SwitchCase) - -AST_NODE(Switch, "Switch"_id) - ast_ptr target; - ast_ptr sep; - ast_list branches; - ast_ptr lastBranch; - AST_MEMBER(Switch, &target, &sep, &branches, &lastBranch) -AST_END(Switch) - -AST_NODE(IfCond, "IfCond"_id) - ast_ptr condition; - ast_ptr assign; - AST_MEMBER(IfCond, &condition, &assign) -AST_END(IfCond) - -AST_NODE(If, "If"_id) - ast_ptr sep; - ast_sel_list nodes; - AST_MEMBER(If, &sep, &nodes) -AST_END(If) - -AST_NODE(Unless, "Unless"_id) - ast_ptr sep; - ast_sel_list nodes; - AST_MEMBER(Unless, &sep, &nodes) -AST_END(Unless) - -AST_NODE(While, "While"_id) - ast_ptr condition; - ast_ptr body; - AST_MEMBER(While, &condition, &body) -AST_END(While) - -AST_NODE(for_step_value, "for_step_value"_id) - ast_ptr value; - AST_MEMBER(for_step_value, &value) -AST_END(for_step_value) - -AST_NODE(For, "For"_id) - ast_ptr varName; - ast_ptr startValue; - ast_ptr stopValue; - ast_ptr stepValue; - ast_ptr body; - AST_MEMBER(For, &varName, &startValue, &stopValue, &stepValue, &body) -AST_END(For) - -class AssignableNameList_t; -class star_exp_t; - -AST_NODE(ForEach, "ForEach"_id) - ast_ptr nameList; - ast_sel loopValue; - ast_ptr body; - AST_MEMBER(ForEach, &nameList, &loopValue, &body) -AST_END(ForEach) - -AST_NODE(Do, "Do"_id) - ast_ptr body; - AST_MEMBER(Do, &body) -AST_END(Do) - -class CompInner_t; -class Statement_t; - -AST_NODE(Comprehension, "Comprehension"_id) - ast_sel value; - ast_ptr forLoop; - AST_MEMBER(Comprehension, &value, &forLoop) -AST_END(Comprehension) - -AST_NODE(comp_value, "comp_value"_id) - ast_ptr value; - AST_MEMBER(comp_value, &value) -AST_END(comp_value) - -AST_NODE(TblComprehension, "TblComprehension"_id) - ast_ptr key; - ast_ptr value; - ast_ptr forLoop; - AST_MEMBER(TblComprehension, &key, &value, &forLoop) -AST_END(TblComprehension) - -AST_NODE(star_exp, "star_exp"_id) - ast_ptr value; - AST_MEMBER(star_exp, &value) -AST_END(star_exp) - -AST_NODE(CompForEach, "CompForEach"_id) - ast_ptr nameList; - ast_sel loopValue; - AST_MEMBER(CompForEach, &nameList, &loopValue) -AST_END(CompForEach) - -AST_NODE(CompFor, "CompFor"_id) - ast_ptr varName; - ast_ptr startValue; - ast_ptr stopValue; - ast_ptr stepValue; - AST_MEMBER(CompFor, &varName, &startValue, &stopValue, &stepValue) -AST_END(CompFor) - -AST_NODE(CompInner, "CompInner"_id) - ast_ptr sep; - ast_sel_list items; - AST_MEMBER(CompInner, &sep, &items) -AST_END(CompInner) - -class TableBlock_t; - -AST_NODE(Assign, "Assign"_id) - ast_ptr sep; - ast_sel_list values; - AST_MEMBER(Assign, &sep, &values) -AST_END(Assign) - -AST_LEAF(update_op, "update_op"_id) -AST_END(update_op) - -AST_NODE(Update, "Update"_id) - ast_ptr op; - ast_ptr value; - AST_MEMBER(Update, &op, &value) -AST_END(Update) - -AST_LEAF(BinaryOperator, "BinaryOperator"_id) -AST_END(BinaryOperator) - -class AssignableChain_t; - -AST_NODE(Assignable, "Assignable"_id) - ast_sel item; - AST_MEMBER(Assignable, &item) -AST_END(Assignable) - -class Value_t; - -AST_NODE(exp_op_value, "exp_op_value"_id) - ast_ptr op; - ast_ptr value; - AST_MEMBER(exp_op_value, &op, &value) -AST_END(exp_op_value) - -AST_NODE(Exp, "Exp"_id) - ast_ptr value; - ast_list opValues; - AST_MEMBER(Exp, &value, &opValues) -AST_END(Exp) - -class Parens_t; - -AST_NODE(Callable, "Callable"_id) - ast_sel item; - AST_MEMBER(Callable, &item) -AST_END(Callable) - -AST_NODE(variable_pair, "variable_pair"_id) - ast_ptr name; - AST_MEMBER(variable_pair, &name) -AST_END(variable_pair) - -class DoubleString_t; -class SingleString_t; - -AST_NODE(normal_pair, "normal_pair"_id) - ast_sel key; - ast_sel value; - AST_MEMBER(normal_pair, &key, &value) -AST_END(normal_pair) - -AST_NODE(simple_table, "simple_table"_id) - ast_ptr sep; - ast_sel_list pairs; - AST_MEMBER(simple_table, &sep, &pairs) -AST_END(simple_table) - -class String_t; -class const_value_t; -class ClassDecl_t; -class unary_exp_t; -class TableLit_t; -class FunLit_t; - -AST_NODE(SimpleValue, "SimpleValue"_id) - ast_sel value; - AST_MEMBER(SimpleValue, &value) -AST_END(SimpleValue) - -AST_LEAF(LuaStringOpen, "LuaStringOpen"_id) -AST_END(LuaStringOpen) - -AST_LEAF(LuaStringContent, "LuaStringContent"_id) -AST_END(LuaStringContent) - -AST_LEAF(LuaStringClose, "LuaStringClose"_id) -AST_END(LuaStringClose) - -AST_NODE(LuaString, "LuaString"_id) - ast_ptr open; - ast_ptr content; - ast_ptr close; - AST_MEMBER(LuaString, &open, &content, &close) -AST_END(LuaString) - -AST_LEAF(SingleString, "SingleString"_id) -AST_END(SingleString) - -AST_LEAF(double_string_inner, "double_string_inner"_id) -AST_END(double_string_inner) - -AST_NODE(double_string_content, "double_string_content"_id) - ast_sel content; - AST_MEMBER(double_string_content, &content) -AST_END(double_string_content) - -AST_NODE(DoubleString, "DoubleString"_id) - ast_ptr sep; - ast_list segments; - AST_MEMBER(DoubleString, &sep, &segments) -AST_END(DoubleString) - -AST_NODE(String, "String"_id) - ast_sel str; - AST_MEMBER(String, &str) -AST_END(String) - -AST_NODE(DotChainItem, "DotChainItem"_id) - ast_ptr name; - AST_MEMBER(DotChainItem, &name) -AST_END(DotChainItem) - -AST_NODE(ColonChainItem, "ColonChainItem"_id) - ast_sel name; - bool switchToDot = false; - AST_MEMBER(ColonChainItem, &name) -AST_END(ColonChainItem) - -class default_value_t; - -AST_NODE(Slice, "Slice"_id) - ast_sel startValue; - ast_sel stopValue; - ast_sel stepValue; - AST_MEMBER(Slice, &startValue, &stopValue, &stepValue) -AST_END(Slice) - -AST_NODE(Parens, "Parens"_id) - ast_ptr expr; - AST_MEMBER(Parens, &expr) -AST_END(Parens) - -AST_NODE(Invoke, "Invoke"_id) - ast_ptr sep; - ast_sel_list args; - AST_MEMBER(Invoke, &sep, &args) -AST_END(Invoke) - -class InvokeArgs_t; - -AST_NODE(ChainValue, "ChainValue"_id) - ast_ptr sep; - ast_sel_list items; - AST_MEMBER(ChainValue, &sep, &items) -AST_END(ChainValue) - -AST_NODE(AssignableChain, "AssignableChain"_id) - ast_ptr sep; - ast_sel_list items; - AST_MEMBER(AssignableChain, &sep, &items) -AST_END(AssignableChain) - -AST_NODE(Value, "Value"_id) - ast_sel item; - AST_MEMBER(Value, &item) -AST_END(Value) - -AST_LEAF(default_value, "default_value"_id) -AST_END(default_value) - -AST_NODE(TableLit, "TableLit"_id) - ast_ptr sep; - ast_sel_list values; - AST_MEMBER(TableLit, &sep, &values) -AST_END(TableLit) - -AST_NODE(TableBlock, "TableBlock"_id) - ast_ptr sep; - ast_sel_list values; - AST_MEMBER(TableBlock, &sep, &values) -AST_END(TableBlock) - -AST_NODE(class_member_list, "class_member_list"_id) - ast_ptr sep; - ast_sel_list values; - AST_MEMBER(class_member_list, &sep, &values) -AST_END(class_member_list) - -AST_NODE(ClassBlock, "ClassBlock"_id) - ast_ptr sep; - ast_sel_list contents; - AST_MEMBER(ClassBlock, &sep, &contents) -AST_END(ClassBlock) - -AST_NODE(ClassDecl, "ClassDecl"_id) - ast_ptr name; - ast_ptr extend; - ast_ptr body; - AST_MEMBER(ClassDecl, &name, &extend, &body) -AST_END(ClassDecl) - -AST_NODE(export_values, "export_values"_id) - ast_ptr nameList; - ast_ptr valueList; - AST_MEMBER(export_values, &nameList, &valueList) -AST_END(export_values) - -AST_LEAF(export_op, "export_op"_id) -AST_END(export_op) - -AST_NODE(Export, "Export"_id) - ast_sel item; - AST_MEMBER(Export, &item) -AST_END(Export) - -AST_NODE(FnArgDef, "FnArgDef"_id) - ast_sel name; - ast_ptr defaultValue; - AST_MEMBER(FnArgDef, &name, &defaultValue) -AST_END(FnArgDef) - -AST_NODE(FnArgDefList, "FnArgDefList"_id) - ast_ptr sep; - ast_list definitions; - ast_ptr varArg; - AST_MEMBER(FnArgDefList, &sep, &definitions, &varArg) -AST_END(FnArgDefList) - -AST_NODE(outer_var_shadow, "outer_var_shadow"_id) - ast_ptr varList; - AST_MEMBER(outer_var_shadow, &varList) -AST_END(outer_var_shadow) - -AST_NODE(FnArgsDef, "FnArgsDef"_id) - ast_ptr defList; - ast_ptr shadowOption; - AST_MEMBER(FnArgsDef, &defList, &shadowOption) -AST_END(FnArgsDef) - -AST_LEAF(fn_arrow, "fn_arrow"_id) -AST_END(fn_arrow) - -AST_NODE(FunLit, "FunLit"_id) - ast_ptr argsDef; - ast_ptr arrow; - ast_ptr body; - AST_MEMBER(FunLit, &argsDef, &arrow, &body) -AST_END(FunLit) - -AST_NODE(NameOrDestructure, "NameOrDestructure"_id) - ast_sel item; - AST_MEMBER(NameOrDestructure, &item) -AST_END(NameOrDestructure) - -AST_NODE(AssignableNameList, "AssignableNameList"_id) - ast_ptr sep; - ast_list items; - AST_MEMBER(AssignableNameList, &sep, &items) -AST_END(AssignableNameList) - -AST_NODE(InvokeArgs, "InvokeArgs"_id) - ast_ptr sep; - ast_sel_list args; - AST_MEMBER(InvokeArgs, &sep, &args) -AST_END(InvokeArgs) - -AST_LEAF(const_value, "const_value"_id) -AST_END(const_value) - -AST_NODE(unary_exp, "unary_exp"_id) - ast_ptr item; - AST_MEMBER(unary_exp, &item) -AST_END(unary_exp) - -AST_NODE(ExpListAssign, "ExpListAssign"_id) - ast_ptr expList; - ast_sel action; - AST_MEMBER(ExpListAssign, &expList, &action) -AST_END(ExpListAssign) - -AST_NODE(if_else_line, "if_else_line"_id) - ast_ptr condition; - ast_sel elseExpr; - AST_MEMBER(if_else_line, &condition, &elseExpr) -AST_END(if_else_line) - -AST_NODE(unless_line, "unless_line"_id) - ast_ptr condition; - AST_MEMBER(unless_line, &condition) -AST_END(unless_line) - -AST_NODE(statement_appendix, "statement_appendix"_id) - ast_sel item; - AST_MEMBER(statement_appendix, &item) -AST_END(statement_appendix) - -AST_LEAF(BreakLoop, "BreakLoop"_id) -AST_END(BreakLoop) - -AST_NODE(Statement, "Statement"_id) - ast_sel content; - ast_ptr appendix; - AST_MEMBER(Statement, &content, &appendix) -AST_END(Statement) - -class Block_t; - -AST_NODE(Body, "Body"_id) - ast_sel content; - AST_MEMBER(Body, &content) -AST_END(Body) - -AST_NODE(Block, "Block"_id) - ast_ptr sep; - ast_list statements; - AST_MEMBER(Block, &sep, &statements) -AST_END(Block) - -AST_NODE(File, "File"_id) - ast_ptr block; - AST_MEMBER(File, &block) -AST_END(File) - -} // namespace MoonP diff --git a/MoonParser/moon_compiler.cpp b/MoonParser/moon_compiler.cpp deleted file mode 100644 index 85b19ff..0000000 --- a/MoonParser/moon_compiler.cpp +++ /dev/null @@ -1,3851 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -using namespace std::string_view_literals; -#include "parser.hpp" -#include "moon_ast.h" -#include "moon_compiler.h" - -namespace MoonP { - -#define BLOCK_START do { -#define BLOCK_END } while (false); -#define BREAK_IF(cond) if (cond) break - -typedef std::list str_list; - -inline std::string s(std::string_view sv) { - return std::string(sv); -} - -class MoonCompliler { -public: - std::pair complile(const std::string& codes, bool lintGlobalVar, bool implicitReturnRoot, bool lineNumber) { - _lintGlobalVar = lintGlobalVar; - _lineNumber = lineNumber; - _input = _converter.from_bytes(codes); - error_list el; - State st; - ast_ptr root; - try { - root = parse(_input, File, el, &st); - } catch (const std::logic_error& error) { - clear(); - return {Empty, error.what()}; - } - if (root) { - try { - str_list out; - pushScope(); - transformBlock(root->block, out, implicitReturnRoot); - popScope(); - return {std::move(out.back()), Empty}; - } catch (const std::logic_error& error) { - clear(); - return {Empty, error.what()}; - } - } else { - clearBuf(); - for (error_list::iterator it = el.begin(); it != el.end(); ++it) { - const error& err = *it; - _buf << debugInfo("Syntax error."sv, &err); - } - std::pair result{Empty, clearBuf()}; - clear(); - return result; - } - } - - const std::unordered_map>& getGlobals() const { - return _globals; - } - - void clear() { - _indentOffset = 0; - _scopes.clear(); - _codeCache.clear(); - std::stack emptyWith; - _withVars.swap(emptyWith); - std::stack emptyContinue; - _continueVars.swap(emptyContinue); - _buf.str(""); - _buf.clear(); - _joinBuf.str(""); - _joinBuf.clear(); - _globals.clear(); - _input.clear(); - } -private: - bool _lintGlobalVar = false; - bool _lineNumber = false; - int _indentOffset = 0; - Converter _converter; - input _input; - std::list _codeCache; - std::stack _withVars; - std::stack _continueVars; - std::unordered_map> _globals; - std::ostringstream _buf; - std::ostringstream _joinBuf; - std::string _newLine = "\n"; - enum class LocalMode { - None = 0, - Capital = 1, - Any = 2 - }; - enum class ExportMode { - None = 0, - Capital = 1, - Any = 2 - }; - struct Scope { - ExportMode mode = ExportMode::None; - std::unique_ptr> vars; - std::unique_ptr> allows; - std::unique_ptr> exports; - }; - std::list _scopes; - static const std::string Empty; - - enum class MemType { - Builtin, - Common, - Property - }; - - struct ClassMember { - std::string item; - MemType type; - ast_node* node; - }; - - struct DestructItem { - bool isVariable = false; - std::string name; - std::string structure; - }; - - struct Destructure { - std::string value; - std::list items; - }; - - enum class ExpUsage { - Return, - Assignment, - Common, - Closure - }; - - enum class IfUsage { - Return, - Closure, - Common - }; - - void pushScope() { - _scopes.emplace_back(); - _scopes.back().vars = std::make_unique>(); - } - - void popScope() { - _scopes.pop_back(); - } - - bool isDefined(const std::string& name) { - bool isDefined = false; - int mode = int(std::isupper(name[0]) ? ExportMode::Capital : ExportMode::Any); - const auto& current = _scopes.back(); - if (int(current.mode) >= mode) { - if (current.exports) { - if (current.exports->find(name) != current.exports->end()) { - isDefined = true; - current.vars->insert(name); - } - } else { - isDefined = true; - current.vars->insert(name); - } - } - decltype(_scopes.back().allows.get()) allows = nullptr; - for (auto it = _scopes.rbegin(); it != _scopes.rend(); ++it) { - if (it->allows) allows = it->allows.get(); - } - bool checkShadowScopeOnly = false; - if (allows) { - checkShadowScopeOnly = allows->find(name) == allows->end(); - } - for (auto it = _scopes.rbegin(); it != _scopes.rend(); ++it) { - auto vars = it->vars.get(); - if (vars->find(name) != vars->end()) { - isDefined = true; - break; - } - if (checkShadowScopeOnly && it->allows) break; - } - return isDefined; - } - - bool isSolidDefined(const std::string& name) { - bool isDefined = false; - for (auto it = _scopes.rbegin(); it != _scopes.rend(); ++it) { - auto vars = it->vars.get(); - if (vars->find(name) != vars->end()) { - isDefined = true; - break; - } - } - return isDefined; - } - - void markVarShadowed() { - auto& scope = _scopes.back(); - scope.allows = std::make_unique>(); - } - - void markVarExported(ExportMode mode, bool specified) { - auto& scope = _scopes.back(); - scope.mode = mode; - if (specified && !scope.exports) { - scope.exports = std::make_unique>(); - } - } - - void addExportedVar(const std::string& name) { - auto& scope = _scopes.back(); - scope.exports->insert(name); - } - - void addToAllowList(const std::string& name) { - auto& scope = _scopes.back(); - scope.allows->insert(name); - } - - void forceAddToScope(const std::string& name) { - auto& scope = _scopes.back(); - scope.vars->insert(name); - } - - Scope& currentScope() { - return _scopes.back(); - } - - bool addToScope(const std::string& name) { - bool defined = isDefined(name); - if (!defined) { - auto& scope = currentScope(); - scope.vars->insert(name); - } - return !defined; - } - - std::string getUnusedName(std::string_view name) { - int index = 0; - std::string newName; - do { - newName = s(name) + std::to_string(index); - index++; - } while (isSolidDefined(newName)); - return newName; - } - - const std::string nll(ast_node* node) { - if (_lineNumber) { - return s(" -- "sv) + std::to_string(node->m_begin.m_line) + _newLine; - } else { - return _newLine; - } - } - - const std::string nlr(ast_node* node) { - if (_lineNumber) { - return s(" -- "sv) + std::to_string(node->m_end.m_line) + _newLine; - } else { - return _newLine; - } - } - - void incIndentOffset() { - _indentOffset++; - } - - void decIndentOffset() { - _indentOffset--; - } - - std::string indent() { - return std::string((_scopes.size() - 1 + _indentOffset) * 2, ' '); - } - - std::string indent(int offset) { - return std::string((_scopes.size() - 1 + _indentOffset + offset) * 2, ' '); - } - - std::string clearBuf() { - std::string str = _buf.str(); - _buf.str(""); - _buf.clear(); - return str; - } - - std::string join(const str_list& items) { - if (items.empty()) return Empty; - else if (items.size() == 1) return items.front(); - for (const auto& item : items) { - _joinBuf << item; - } - auto result = _joinBuf.str(); - _joinBuf.str(""); - _joinBuf.clear(); - return result; - } - - std::string join(const str_list& items, std::string_view sep) { - if (items.empty()) return Empty; - else if (items.size() == 1) return items.front(); - std::string sepStr = s(sep); - auto begin = ++items.begin(); - _joinBuf << items.front(); - for (auto it = begin; it != items.end(); ++it) { - _joinBuf << sepStr << *it; - } - auto result = _joinBuf.str(); - _joinBuf.str(""); - _joinBuf.clear(); - return result; - } - - std::string toString(ast_node* node) { - return _converter.to_bytes(std::wstring(node->m_begin.m_it, node->m_end.m_it)); - } - - std::string toString(input::iterator begin, input::iterator end) { - return _converter.to_bytes(std::wstring(begin, end)); - } - - Value_t* singleValueFrom(ast_node* item) { - Exp_t* exp = nullptr; - switch (item->getId()) { - case "Exp"_id: - exp = static_cast(item); - break; - case "ExpList"_id: { - auto expList = static_cast(item); - if (expList->exprs.size() == 1) { - exp = static_cast(expList->exprs.front()); - } - break; - } - case "ExpListLow"_id: { - auto expList = static_cast(item); - if (expList->exprs.size() == 1) { - exp = static_cast(expList->exprs.front()); - } - break; - } - } - if (!exp) return nullptr; - if (exp->opValues.empty()) { - return exp->value.get(); - } - return nullptr; - } - - SimpleValue_t* simpleSingleValueFrom(ast_node* expList) { - auto value = singleValueFrom(expList); - if (value && value->item.is()) { - return static_cast(value->item.get()); - } - return nullptr; - } - - Value_t* firstValueFrom(ast_node* item) { - Exp_t* exp = nullptr; - if (auto expList = ast_cast(item)) { - if (!expList->exprs.empty()) { - exp = static_cast(expList->exprs.front()); - } - } else { - exp = ast_cast(item); - } - return exp->value.get(); - } - - Statement_t* lastStatementFrom(Body_t* body) { - if (auto stmt = body->content.as()) { - return stmt; - } else { - auto node = body->content.to()->statements.objects().back(); - return static_cast(node); - } - } - - Statement_t* lastStatementFrom(Block_t* block) { - auto node = block->statements.objects().back(); - return static_cast(node); - } - - template - ast_ptr toAst(std::string_view codes, rule& r, ast_node* parent) { - _codeCache.push_back(_converter.from_bytes(s(codes))); - error_list el; - State st; - auto ptr = parse(_codeCache.back(), r, el, &st); - ptr->traverse([&](ast_node* node) { - node->m_begin.m_line = parent->m_begin.m_line; - node->m_end.m_line = parent->m_begin.m_line; - return traversal::Continue; - }); - return ptr; - } - - bool matchAst(rule& r, std::string_view codes) { - error_list el; - State st; - input i = _converter.from_bytes(s(codes)); - auto rEnd = rule(r >> eof()); - ast_ptr result(_parse(i, rEnd, el, &st)); - return result; - } - - bool isChainValueCall(ChainValue_t* chainValue) { - return ast_is(chainValue->items.back()); - } - - std::string singleVariableFrom(ast_node* expList) { - if (!ast_is(expList)) return Empty; - BLOCK_START - auto value = singleValueFrom(expList); - BREAK_IF(!value); - auto chainValue = value->getByPath(); - BREAK_IF(!chainValue); - BREAK_IF(chainValue->items.size() != 1); - auto callable = ast_cast(chainValue->items.front()); - BREAK_IF(!callable || !callable->item.is()); - str_list tmp; - transformCallable(callable, tmp, false); - return tmp.back(); - BLOCK_END - return Empty; - } - - bool isColonChain(ChainValue_t* chainValue) { - return ast_is(chainValue->items.back()); - } - - bool hasKeywordColonChainItem(ChainValue_t* chainValue) { - const auto& chainList = chainValue->items.objects(); - for (auto it = chainList.begin(); it != chainList.end(); ++it) { - if (auto colonItem = ast_cast(*it)) { - if (colonItem->name.is()) { - return true; - } - } - } - return false; - } - - bool isAssignable(const node_container& chainItems) { - if (chainItems.size() == 1) { - auto firstItem = chainItems.back(); - if (auto callable = ast_cast(firstItem)) { - switch (callable->item->getId()) { - case "Variable"_id: - case "SelfName"_id: - return true; - } - } else if (firstItem->getId() == "DotChainItem"_id) { - return true; - } - } else { - auto lastItem = chainItems.back(); - switch (lastItem->getId()) { - case "DotChainItem"_id: - case "Exp"_id: - return true; - } - } - return false; - } - - bool isAssignable(Exp_t* exp) { - if (auto value = singleValueFrom(exp)) { - auto item = value->item.get(); - switch (item->getId()) { - case "simple_table"_id: - return true; - case "SimpleValue"_id: { - auto simpleValue = static_cast(item); - if (simpleValue->value.is()) { - return true; - } - return false; - } - case "ChainValue"_id: { - auto chainValue = static_cast(item); - return isAssignable(chainValue->items.objects()); - } - } - } - return false; - } - - bool isAssignable(Assignable_t* assignable) { - if (auto assignableChain = ast_cast(assignable->item)) { - return isAssignable(assignableChain->items.objects()); - } - return true; - } - - void checkAssignable(ExpList_t* expList) { - for (auto exp_ : expList->exprs.objects()) { - Exp_t* exp = static_cast(exp_); - if (!isAssignable(exp)) { - throw std::logic_error(debugInfo("Left hand expression is not assignable."sv, exp)); - } - } - } - - std::string debugInfo(std::string_view msg, const input_range* loc) { - const int ASCII = 255; - int length = loc->m_begin.m_line; - auto begin = _input.begin(); - auto end = _input.end(); - int count = 0; - for (auto it = _input.begin(); it != _input.end(); ++it) { - if (*it == '\n') { - if (count + 1 == length) { - end = it; - break; - } else { - begin = it + 1; - } - count++; - } - } - auto line = _converter.to_bytes(std::wstring(begin, end)); - int oldCol = loc->m_begin.m_col; - int col = loc->m_begin.m_col - 1; - auto it = begin; - for (int i = 0; i < oldCol; ++i) { - if (*it > ASCII) { - ++col; - } - ++it; - } - replace(line, "\t"sv, " "sv); - std::ostringstream buf; - buf << loc->m_begin.m_line << ": "sv << msg << - '\n' << line << '\n' << std::string(col, ' ') << "^"sv; - return buf.str(); - } - - void transformStatement(Statement_t* statement, str_list& out) { - auto x = statement; - if (statement->appendix) { - if (auto assignment = assignmentFrom(statement)) { - auto preDefine = getPredefine(transformAssignDefs(assignment->expList)); - if (!preDefine.empty()) out.push_back(preDefine + nll(statement)); - } - auto appendix = statement->appendix.get(); - switch (appendix->item->getId()) { - case "if_else_line"_id: { - auto if_else_line = appendix->item.to(); - auto ifNode = x->new_ptr(); - - auto ifCond = x->new_ptr(); - ifCond->condition.set(if_else_line->condition); - ifNode->nodes.push_back(ifCond); - - auto stmt = x->new_ptr(); - stmt->content.set(statement->content); - auto body = x->new_ptr(); - body->content.set(stmt); - ifNode->nodes.push_back(body); - - if (!ast_is(if_else_line->elseExpr)) { - auto expList = x->new_ptr(); - expList->exprs.push_back(if_else_line->elseExpr); - auto expListAssign = x->new_ptr(); - expListAssign->expList.set(expList); - auto stmt = x->new_ptr(); - stmt->content.set(expListAssign); - auto body = x->new_ptr(); - body->content.set(stmt); - ifNode->nodes.push_back(body); - } - - statement->appendix.set(nullptr); - auto simpleValue = x->new_ptr(); - simpleValue->value.set(ifNode); - auto value = x->new_ptr(); - value->item.set(simpleValue); - auto exp = x->new_ptr(); - exp->value.set(value); - auto expList = x->new_ptr(); - expList->exprs.push_back(exp); - auto expListAssign = x->new_ptr(); - expListAssign->expList.set(expList); - statement->content.set(expListAssign); - break; - } - case "unless_line"_id: { - auto unless_line = appendix->item.to(); - auto unless = x->new_ptr(); - - auto ifCond = x->new_ptr(); - ifCond->condition.set(unless_line->condition); - unless->nodes.push_back(ifCond); - - auto stmt = x->new_ptr(); - stmt->content.set(statement->content); - auto body = x->new_ptr(); - body->content.set(stmt); - unless->nodes.push_back(body); - - statement->appendix.set(nullptr); - auto simpleValue = x->new_ptr(); - simpleValue->value.set(unless); - auto value = x->new_ptr(); - value->item.set(simpleValue); - auto exp = x->new_ptr(); - exp->value.set(value); - auto exprList = x->new_ptr(); - exprList->exprs.push_back(exp); - auto expListAssign = x->new_ptr(); - expListAssign->expList.set(exprList); - statement->content.set(expListAssign); - break; - } - case "CompInner"_id: { - auto compInner = appendix->item.to(); - auto comp = x->new_ptr(); - comp->forLoop.set(compInner); - auto stmt = x->new_ptr(); - stmt->content.set(statement->content); - comp->value.set(stmt); - auto simpleValue = x->new_ptr(); - simpleValue->value.set(comp); - auto value = x->new_ptr(); - value->item.set(simpleValue); - auto exp = x->new_ptr(); - exp->value.set(value); - auto expList = x->new_ptr(); - expList->exprs.push_back(exp); - auto expListAssign = x->new_ptr(); - expListAssign->expList.set(expList); - statement->content.set(expListAssign); - statement->appendix.set(nullptr); - break; - } - default: break; - } - } - auto content = statement->content.get(); - if (!content) { - out.push_back(Empty); - return; - } - switch (content->getId()) { - case "Import"_id: transformImport(static_cast(content), out); break; - case "While"_id: transformWhile(static_cast(content), out); break; - case "For"_id: transformFor(static_cast(content), out); break; - case "ForEach"_id: transformForEach(static_cast(content), out); break; - case "Return"_id: transformReturn(static_cast(content), out); break; - case "Local"_id: transformLocal(static_cast(content), out); break; - case "Export"_id: transformExport(static_cast(content), out); break; - case "BreakLoop"_id: transformBreakLoop(static_cast(content), out); break; - case "ExpListAssign"_id: { - auto expListAssign = static_cast(content); - if (expListAssign->action) { - transformAssignment(expListAssign, out); - } else { - auto expList = expListAssign->expList.get(); - if (expList->exprs.objects().empty()) { - out.push_back(Empty); - break; - } - if (auto singleValue = singleValueFrom(expList)) { - if (auto simpleValue = singleValue->item.as()) { - auto value = simpleValue->value.get(); - bool specialSingleValue = true; - switch (value->getId()) { - case "If"_id: transformIf(static_cast(value), out); break; - case "ClassDecl"_id: transformClassDecl(static_cast(value), out); break; - case "Unless"_id: transformUnless(static_cast(value), out); break; - case "Switch"_id: transformSwitch(static_cast(value), out); break; - case "With"_id: transformWith(static_cast(value), out); break; - case "ForEach"_id: transformForEach(static_cast(value), out); break; - case "For"_id: transformFor(static_cast(value), out); break; - case "While"_id: transformWhile(static_cast(value), out); break; - case "Do"_id: transformDo(static_cast(value), out); break; - case "Comprehension"_id: transformCompCommon(static_cast(value), out); break; - default: specialSingleValue = false; break; - } - if (specialSingleValue) { - break; - } - } - if (auto chainValue = singleValue->item.as()) { - if (isChainValueCall(chainValue)) { - transformChainValue(chainValue, out, ExpUsage::Common); - break; - } - } - } - auto assign = x->new_ptr(); - assign->values.dup(expList->exprs); - auto assignment = x->new_ptr(); - assignment->expList.set(toAst("_", ExpList, x)); - assignment->action.set(assign); - transformAssignment(assignment, out); - } - break; - } - default: break; - } - } - - str_list getAssignVars(ExpListAssign_t* assignment) { - str_list vars; - if (!assignment->action.is()) return vars; - for (auto exp : assignment->expList->exprs.objects()) { - auto var = singleVariableFrom(exp); - vars.push_back(var.empty() ? Empty : var); - } - return vars; - } - - str_list getAssignVars(With_t* with) { - str_list vars; - for (auto exp : with->valueList->exprs.objects()) { - auto var = singleVariableFrom(exp); - vars.push_back(var.empty() ? Empty : var); - } - return vars; - } - - str_list getAssignDefs(ExpList_t* expList) { - str_list preDefs; - for (auto exp_ : expList->exprs.objects()) { - auto exp = static_cast(exp_); - if (auto value = singleValueFrom(exp)) { - if (auto chain = value->item.as()) { - BLOCK_START - BREAK_IF(chain->items.size() != 1); - auto callable = ast_cast(chain->items.front()); - BREAK_IF(!callable); - auto var = callable->item.as(); - BREAK_IF(!var); - auto name = toString(var); - if (!isDefined(name)) { - preDefs.push_back(name); - } - BLOCK_END - } - } else { - throw std::logic_error(debugInfo("Left hand expression is not assignable."sv, exp)); - } - } - return preDefs; - } - - str_list transformAssignDefs(ExpList_t* expList) { - str_list preDefs; - for (auto exp_ : expList->exprs.objects()) { - auto exp = static_cast(exp_); - if (auto value = singleValueFrom(exp)) { - if (auto chain = value->item.as()) { - BLOCK_START - BREAK_IF(chain->items.size() != 1); - auto callable = ast_cast(chain->items.front()); - BREAK_IF(!callable); - auto var = callable->item.as(); - BREAK_IF(!var); - auto name = toString(var); - if (addToScope(name)) { - preDefs.push_back(name); - } - BLOCK_END - } - } else { - throw std::logic_error(debugInfo("Left hand expression is not assignable."sv, exp)); - } - } - return preDefs; - } - - std::string getPredefine(const str_list& defs) { - if (defs.empty()) return Empty; - return indent() + s("local "sv) + join(defs, ", "sv); - } - - std::string getDestrucureDefine(ExpListAssign_t* assignment) { - auto info = extractDestructureInfo(assignment); - if (!info.first.empty()) { - for (const auto& destruct : info.first) { - str_list defs; - for (const auto& item : destruct.items) { - if (item.isVariable && addToScope(item.name)) { - defs.push_back(item.name); - } - } - if (!defs.empty()) _buf << indent() << "local "sv << join(defs,", "sv); - } - } - return clearBuf(); - } - - std::string getPredefine(ExpListAssign_t* assignment) { - auto preDefine = getDestrucureDefine(assignment); - if (preDefine.empty()) { - preDefine = getPredefine(transformAssignDefs(assignment->expList)); - } - return preDefine.empty() ? preDefine : preDefine + nll(assignment); - } - - ExpList_t* expListFrom(Statement_t* statement) { - if (auto expListAssign = statement->content.as()) { - if (!expListAssign->action) { - return expListAssign->expList.get(); - } - } - return nullptr; - } - - ExpListAssign_t* assignmentFrom(Statement_t* statement) { - if (auto expListAssign = statement->content.as()) { - if (expListAssign->action) { - return expListAssign; - } - } - return nullptr; - } - - void assignLastExplist(ExpList_t* expList, Body_t* body) { - auto last = lastStatementFrom(body); - if (!last) return; - bool lastAssignable = expListFrom(last) || ast_is(last->content); - if (lastAssignable) { - auto x = last; - auto newAssignment = x->new_ptr(); - newAssignment->expList.set(expList); - auto assign = x->new_ptr(); - if (auto valueList = last->content.as()) { - assign->values.dup(valueList->expList->exprs); - } else { - auto simpleValue = x->new_ptr(); - simpleValue->value.set(last->content); - auto value = x->new_ptr(); - value->item.set(simpleValue); - auto exp = x->new_ptr(); - exp->value.set(value); - assign->values.push_back(exp); - } - newAssignment->action.set(assign); - last->content.set(newAssignment); - } - } - - void transformAssignment(ExpListAssign_t* assignment, str_list& out) { - checkAssignable(assignment->expList); - BLOCK_START - auto assign = ast_cast(assignment->action); - BREAK_IF(!assign || assign->values.objects().size() != 1); - auto value = assign->values.objects().front(); - if (ast_is(value)) { - if (auto val = simpleSingleValueFrom(value)) { - value = val->value.get(); - } - } - switch (value->getId()) { - case "If"_id: - case "Unless"_id: { - auto expList = assignment->expList.get(); - str_list temp; - auto defs = transformAssignDefs(expList); - if (!defs.empty()) temp.push_back(getPredefine(defs) + nll(expList)); - value->traverse([&](ast_node* node) { - switch (node->getId()) { - case "IfCond"_id: return traversal::Return; - case "Body"_id: { - auto body = static_cast(node); - assignLastExplist(expList, body); - return traversal::Return; - } - default: return traversal::Continue; - } - }); - switch (value->getId()) { - case "If"_id: transformIf(static_cast(value), temp); break; - case "Unless"_id: transformUnless(static_cast(value), temp); break; - } - out.push_back(join(temp)); - return; - } - case "Switch"_id: { - auto switchNode = static_cast(value); - auto expList = assignment->expList.get(); - for (auto branch_ : switchNode->branches.objects()) { - auto branch = static_cast(branch_); - assignLastExplist(expList, branch->body); - } - if (switchNode->lastBranch) { - assignLastExplist(expList, switchNode->lastBranch); - } - std::string preDefine = getPredefine(assignment); - transformSwitch(switchNode, out); - out.back() = preDefine + out.back(); - return; - } - case "With"_id: { - auto withNode = static_cast(value); - str_list temp; - auto expList = assignment->expList.get(); - std::string preDefine = getPredefine(assignment); - transformWith(withNode, temp, expList); - out.push_back(preDefine + temp.back()); - return; - } - case "Do"_id: { - auto doNode = static_cast(value); - auto expList = assignment->expList.get(); - assignLastExplist(expList, doNode->body); - std::string preDefine = getPredefine(assignment); - transformDo(doNode, out); - out.back() = preDefine + out.back(); - return; - } - case "Comprehension"_id: { - auto expList = assignment->expList.get(); - std::string preDefine = getPredefine(assignment); - transformCompInPlace(static_cast(value), expList, out); - out.back() = preDefine + out.back(); - return; - } - case "TblComprehension"_id: { - auto expList = assignment->expList.get(); - std::string preDefine = getPredefine(assignment); - transformTblCompInPlace(static_cast(value), expList, out); - out.back() = preDefine + out.back(); - return; - } - case "For"_id: { - str_list temp; - auto expList = assignment->expList.get(); - std::string preDefine = getPredefine(assignment); - transformForInPlace(static_cast(value), temp, expList); - out.push_back(preDefine + temp.back()); - return; - } - case "ForEach"_id: { - str_list temp; - auto expList = assignment->expList.get(); - std::string preDefine = getPredefine(assignment); - transformForEachInPlace(static_cast(value), temp, expList); - out.push_back(preDefine + temp.back()); - return; - } - case "ClassDecl"_id: { - str_list temp; - auto expList = assignment->expList.get(); - std::string preDefine = getPredefine(assignment); - transformClassDecl(static_cast(value), temp, ExpUsage::Assignment, expList); - out.push_back(preDefine + temp.back()); - return; - } - case "While"_id: { - str_list temp; - auto expList = assignment->expList.get(); - std::string preDefine = getPredefine(assignment); - transformWhileInPlace(static_cast(value), temp, expList); - out.push_back(preDefine + temp.back()); - return; - } - } - auto exp = ast_cast(value); - BREAK_IF(!exp); - if (auto chainValue = exp->value->item.as()) { - if (isColonChain(chainValue)) { - auto assignable = assignment->expList.get(); - std::string preDefine = getPredefine(transformAssignDefs(assignable)); - transformColonChain(chainValue, out, ExpUsage::Assignment, assignable); - auto nl = preDefine.empty() ? Empty : nll(chainValue); - if (!preDefine.empty()) out.back() = preDefine + nl + out.back(); - return; - } else if (hasKeywordColonChainItem(chainValue)) { - transformChainValue(chainValue, out, ExpUsage::Assignment, assignment->expList); - return; - } - } - BLOCK_END - auto info = extractDestructureInfo(assignment); - if (info.first.empty()) { - transformAssignmentCommon(assignment, out); - } else { - str_list temp; - for (const auto& destruct : info.first) { - if (destruct.items.size() == 1) { - auto& pair = destruct.items.front(); - _buf << indent(); - if (pair.isVariable && !isDefined(pair.name)) { - _buf << s("local "sv); - } - _buf << pair.name << " = "sv << info.first.front().value << pair.structure << nll(assignment); - addToScope(pair.name); - temp.push_back(clearBuf()); - } else if (matchAst(Name, destruct.value)) { - str_list defs, names, values; - for (const auto& item : destruct.items) { - if (item.isVariable && addToScope(item.name)) { - defs.push_back(item.name); - } - names.push_back(item.name); - values.push_back(item.structure); - } - for (auto& v : values) v.insert(0, destruct.value); - if (defs.empty()) { - _buf << indent() << join(names, ", "sv) << " = "sv << join(values, ", "sv) << nll(assignment); - } else { - _buf << indent() << "local "sv; - if (defs.size() != names.size()) { - _buf << join(defs,", "sv) << nll(assignment) << indent(); - } - _buf << join(names, ", "sv) << " = "sv << join(values, ", "sv) << nll(assignment); - } - temp.push_back(clearBuf()); - } else { - str_list defs, names, values; - for (const auto& item : destruct.items) { - if (item.isVariable && addToScope(item.name)) { - defs.push_back(item.name); - } - names.push_back(item.name); - values.push_back(item.structure); - } - if (!defs.empty()) _buf << indent() << "local "sv << join(defs,", "sv) << nll(assignment); - _buf << indent() << "do"sv << nll(assignment); - pushScope(); - auto objVar = getUnusedName("_obj_"); - for (auto& v : values) v.insert(0, objVar); - _buf << indent() << "local "sv << objVar << " = "sv << destruct.value << nll(assignment); - _buf << indent() << join(names, ", "sv) << " = "sv << join(values, ", "sv) << nll(assignment); - popScope(); - _buf << indent() << "end"sv << nll(assignment); - temp.push_back(clearBuf()); - } - } - if (info.second) { - transformAssignmentCommon(info.second, temp); - } - out.push_back(join(temp)); - } - } - - void transformAssignItem(ast_node* value, str_list& out) { - switch (value->getId()) { - case "With"_id: transformWithClosure(static_cast(value), out); break; - case "If"_id: transformIf(static_cast(value), out, IfUsage::Closure); break; - case "Switch"_id: transformSwitchClosure(static_cast(value), out); break; - case "TableBlock"_id: transformTableBlock(static_cast(value), out); break; - case "Exp"_id: transformExp(static_cast(value), out); break; - default: break; - } - } - - std::list destructFromExp(ast_node* node) { - const node_container* tableItems = nullptr; - if (ast_cast(node)) { - auto item = singleValueFrom(node)->item.get(); - if (!item) throw std::logic_error(debugInfo("Invalid destructure value."sv, node)); - auto tbA = item->getByPath(); - if (tbA) { - tableItems = &tbA->values.objects(); - } else { - auto tbB = ast_cast(item); - if (tbB) tableItems = &tbB->pairs.objects(); - } - } else if (auto table = ast_cast(node)) { - tableItems = &table->values.objects(); - } - std::list pairs; - int index = 0; - for (auto pair : *tableItems) { - switch (pair->getId()) { - case "Exp"_id: { - ++index; - if (!isAssignable(static_cast(pair))) { - throw std::logic_error(debugInfo("Can't destructure value."sv, pair)); - } - auto value = singleValueFrom(pair); - auto item = value->item.get(); - if (ast_cast(item) || - item->getByPath()) { - auto subPairs = destructFromExp(pair); - for (auto& p : subPairs) { - pairs.push_back({p.isVariable, p.name, - s("["sv) + std::to_string(index) + s("]"sv) + p.structure}); - } - } else { - bool checkGlobal = _lintGlobalVar; - _lintGlobalVar = false; - auto exp = static_cast(pair); - auto varName = singleVariableFrom(exp); - bool isVariable = !varName.empty(); - if (!isVariable) { - str_list temp; - transformExp(exp, temp); - varName = std::move(temp.back()); - } - _lintGlobalVar = checkGlobal; - pairs.push_back({ - isVariable, - varName, - s("["sv) + std::to_string(index) + s("]"sv) - }); - } - break; - } - case "variable_pair"_id: { - auto vp = static_cast(pair); - auto name = toString(vp->name); - pairs.push_back({true, name, s("."sv) + name}); - break; - } - case "normal_pair"_id: { - auto np = static_cast(pair); - auto key = np->key->getByPath(); - if (!key) throw std::logic_error(debugInfo("Invalid key for destructure."sv, np)); - if (auto exp = np->value.as()) { - if (!isAssignable(exp)) throw std::logic_error(debugInfo("Can't destructure value."sv, exp)); - auto item = singleValueFrom(exp)->item.get(); - if (ast_cast(item) || - item->getByPath()) { - auto subPairs = destructFromExp(exp); - for (auto& p : subPairs) { - pairs.push_back({p.isVariable, p.name, - s("."sv) + toString(key) + p.structure}); - } - } else { - bool checkGlobal = _lintGlobalVar; - _lintGlobalVar = false; - auto varName = singleVariableFrom(exp); - bool isVariable = !varName.empty(); - if (!isVariable) { - str_list temp; - transformExp(exp, temp); - varName = std::move(temp.back()); - } - _lintGlobalVar = checkGlobal; - pairs.push_back({ - isVariable, - varName, - s("."sv) + toString(key) - }); - } - break; - } - if (np->value.as()) { - auto subPairs = destructFromExp(pair); - for (auto& p : subPairs) { - pairs.push_back({p.isVariable, p.name, - s("."sv) + toString(key) + p.structure}); - } - } - break; - } - } - } - return pairs; - } - - std::pair, ast_ptr> - extractDestructureInfo(ExpListAssign_t* assignment) { - auto x = assignment; - std::list destructs; - if (!assignment->action.is()) return { destructs, nullptr }; - auto exprs = assignment->expList->exprs.objects(); - auto values = assignment->action.to()->values.objects(); - size_t size = std::max(exprs.size(),values.size()); - ast_ptr var; - if (exprs.size() < size) { - var = toAst("_"sv, Exp, x); - while (exprs.size() < size) exprs.emplace_back(var); - } - ast_ptr nullNode; - if (values.size() < size) { - nullNode = toAst("nil"sv, Exp, x); - while (values.size() < size) values.emplace_back(nullNode); - } - using iter = node_container::iterator; - std::vector> destructPairs; - str_list temp; - for (auto i = exprs.begin(), j = values.begin(); i != exprs.end(); ++i, ++j) { - auto expr = *i; - ast_node* destructNode = expr->getByPath(); - if (destructNode || (destructNode = expr->getByPath())) { - destructPairs.push_back({i,j}); - pushScope(); - transformAssignItem(*j, temp); - popScope(); - auto& destruct = destructs.emplace_back(); - destruct.value = temp.back(); - temp.pop_back(); - auto pairs = destructFromExp(expr); - destruct.items = std::move(pairs); - } - } - for (const auto& p : destructPairs) { - exprs.erase(p.first); - values.erase(p.second); - } - ast_ptr newAssignment; - if (!destructPairs.empty() && !exprs.empty()) { - auto x = assignment; - auto expList = x->new_ptr(); - auto newAssign = x->new_ptr(); - newAssign->expList.set(expList); - for (auto expr : exprs) expList->exprs.push_back(expr); - auto assign = x->new_ptr(); - for (auto value : values) assign->values.push_back(value); - newAssign->action.set(assign); - newAssignment = newAssign; - } - return {std::move(destructs), newAssignment}; - } - - void transformAssignmentCommon(ExpListAssign_t* assignment, str_list& out) { - auto x = assignment; - str_list temp; - auto expList = assignment->expList.get(); - auto action = assignment->action.get(); - switch (action->getId()) { - case "Update"_id: { - auto update = static_cast(action); - auto leftExp = static_cast(expList->exprs.objects().front()); - auto leftValue = singleValueFrom(leftExp); - if (!leftValue) throw std::logic_error(debugInfo("Left hand expression is not assignable."sv, leftExp)); - if (auto chain = leftValue->getByPath()) { - auto tmpChain = x->new_ptr(); - for (auto item : chain->items.objects()) { - bool itemAdded = false; - BLOCK_START - auto exp = ast_cast(item); - BREAK_IF(!exp); - auto var = singleVariableFrom(exp); - BREAK_IF(!var.empty()); - auto upVar = getUnusedName("_update_"); - auto assignment = x->new_ptr(); - assignment->expList.set(toAst(upVar, ExpList, x)); - auto assign = x->new_ptr(); - assign->values.push_back(exp); - assignment->action.set(assign); - transformAssignment(assignment, temp); - tmpChain->items.push_back(toAst(upVar, Exp, x)); - itemAdded = true; - BLOCK_END - if (!itemAdded) tmpChain->items.push_back(item); - } - chain->items.clear(); - chain->items.dup(tmpChain->items); - } - transformValue(leftValue, temp); - auto left = std::move(temp.back()); - temp.pop_back(); - transformExp(update->value, temp); - auto right = std::move(temp.back()); - temp.pop_back(); - if (!singleValueFrom(update->value)) { - right = s("("sv) + right + s(")"sv); - } - _buf << join(temp) << indent() << left << " = "sv << left << - " "sv << toString(update->op) << " "sv << right << nll(assignment); - out.push_back(clearBuf()); - break; - } - case "Assign"_id: { - auto defs = getAssignDefs(expList); - bool oneLined = defs.size() == expList->exprs.objects().size() && - traversal::Stop != action->traverse([&](ast_node* n) { - if (n->getId() == "Callable"_id) { - if (auto name = n->getByPath()) { - for (const auto& def : defs) { - if (def == toString(name)) { - return traversal::Stop; - } - } - } - } - return traversal::Continue; - }); - if (oneLined) { - auto assign = static_cast(action); - for (auto value : assign->values.objects()) { - transformAssignItem(value, temp); - } - std::string preDefine = getPredefine(defs); - for (const auto& def : defs) { - addToScope(def); - } - if (preDefine.empty()) { - transformExpList(expList, temp); - std::string left = std::move(temp.back()); - temp.pop_back(); - out.push_back(indent() + left + s(" = "sv) + join(temp, ", "sv) + nll(assignment)); - } else { - out.push_back(preDefine + s(" = "sv) + join(temp, ", "sv) + nll(assignment)); - } - } - else { - std::string preDefine = getPredefine(defs); - for (const auto& def : defs) { - addToScope(def); - } - transformExpList(expList, temp); - std::string left = temp.back(); - temp.pop_back(); - auto assign = static_cast(action); - for (auto value : assign->values.objects()) { - transformAssignItem(value, temp); - } - out.push_back((preDefine.empty() ? Empty : preDefine + nll(assignment)) + indent() + left + s(" = "sv) + join(temp, ", "sv) + nll(assignment)); - } - break; - } - default: break; - } - } - - void transformCond(const node_container& nodes, str_list& out, IfUsage usage = IfUsage::Common, bool unless = false) { - std::vector> ns(false); - for (auto it = nodes.rbegin(); it != nodes.rend(); ++it) { - ns.push_back(*it); - if (auto cond = ast_cast(*it)) { - if (*it != nodes.front() && cond->assign) { - auto x = *it; - auto newIf = x->new_ptr(); - for (auto j = ns.rbegin(); j != ns.rend(); ++j) { - newIf->nodes.push_back(*j); - } - ns.clear(); - auto simpleValue = x->new_ptr(); - simpleValue->value.set(newIf); - auto value = x->new_ptr(); - value->item.set(simpleValue); - auto exp = x->new_ptr(); - exp->value.set(value); - auto expList = x->new_ptr(); - expList->exprs.push_back(exp); - auto expListAssign = x->new_ptr(); - expListAssign->expList.set(expList); - auto stmt = x->new_ptr(); - stmt->content.set(expListAssign); - auto body = x->new_ptr(); - body->content.set(stmt); - ns.push_back(body.get()); - } - } - } - if (nodes.size() != ns.size()) { - auto x = ns.back(); - auto newIf = x->new_ptr(); - for (auto j = ns.rbegin(); j != ns.rend(); ++j) { - newIf->nodes.push_back(*j); - } - transformCond(newIf->nodes.objects(), out, usage, unless); - return; - } - str_list temp; - if (usage == IfUsage::Closure) { - temp.push_back(s("(function()"sv) + nll(nodes.front())); - pushScope(); - } - std::list> ifCondPairs; - ifCondPairs.emplace_back(); - for (auto node : nodes) { - switch (node->getId()) { - case "IfCond"_id: - ifCondPairs.back().first = static_cast(node); - break; - case "Body"_id: - ifCondPairs.back().second = static_cast(node); - ifCondPairs.emplace_back(); - break; - default: break; - } - } - auto assign = ifCondPairs.front().first->assign.get(); - bool storingValue = false; - ast_ptr extraAssignment; - if (assign) { - auto exp = ifCondPairs.front().first->condition.get(); - auto x = exp; - auto var = singleVariableFrom(exp); - if (var.empty()) { - storingValue = true; - std::string desVar = getUnusedName("_des_"); - if (assign->values.objects().size() == 1) { - auto var = singleVariableFrom(assign->values.objects().front()); - if (!var.empty()) { - desVar = var; - storingValue = false; - } - } - if (storingValue) { - if (usage != IfUsage::Closure) { - temp.push_back(indent() + s("do"sv) + nll(assign)); - pushScope(); - } - auto expList = toAst(desVar, ExpList, x); - auto assignment = x->new_ptr(); - assignment->expList.set(expList); - assignment->action.set(assign); - transformAssignment(assignment, temp); - } - { - auto expList = x->new_ptr(); - expList->exprs.push_back(exp); - auto assignOne = x->new_ptr(); - auto valExp = toAst(desVar, Exp, x); - assignOne->values.push_back(valExp); - auto assignment = x->new_ptr(); - assignment->expList.set(expList); - assignment->action.set(assignOne); - extraAssignment.set(assignment); - ifCondPairs.front().first->condition.set(valExp); - } - } else { - if (!isDefined(var)) { - storingValue = true; - if (usage != IfUsage::Closure) { - temp.push_back(indent() + s("do"sv) + nll(assign)); - pushScope(); - } - } - auto expList = x->new_ptr(); - expList->exprs.push_back(exp); - auto assignment = x->new_ptr(); - assignment->expList.set(expList); - assignment->action.set(assign); - transformAssignment(assignment, temp); - } - } - for (const auto& pair : ifCondPairs) { - if (pair.first) { - str_list tmp; - auto condition = pair.first->condition.get(); - if (unless) { - if (auto value = singleValueFrom(condition)) { - transformValue(value, tmp); - } else { - transformExp(condition, tmp); - tmp.back() = s("("sv) + tmp.back() + s(")"sv); - } - tmp.back().insert(0, s("not "sv)); - unless = false; - } else { - transformExp(condition, tmp); - } - _buf << indent(); - if (pair != ifCondPairs.front()) { - _buf << "else"sv; - } - _buf << "if "sv << tmp.back() << " then"sv << nll(condition); - temp.push_back(clearBuf()); - } - if (pair.second) { - if (!pair.first) { - temp.push_back(indent() + s("else"sv) + nll(pair.second)); - } - pushScope(); - if (pair == ifCondPairs.front() && extraAssignment) { - transformAssignment(extraAssignment, temp); - } - transformBody(pair.second, temp, usage != IfUsage::Common); - popScope(); - } - if (!pair.first) { - temp.push_back(indent() + s("end"sv) + nll(nodes.front())); - break; - } - } - if (storingValue && usage != IfUsage::Closure) { - popScope(); - temp.push_back(indent() + s("end"sv) + nlr(nodes.front())); - } - if (usage == IfUsage::Closure) { - popScope(); - temp.push_back(indent() + s("end)()"sv)); - } - out.push_back(join(temp)); - } - - void transformIf(If_t* ifNode, str_list& out, IfUsage usage = IfUsage::Common) { - transformCond(ifNode->nodes.objects(), out, usage); - } - - void transformUnless(Unless_t* unless, str_list& out, IfUsage usage = IfUsage::Common) { - transformCond(unless->nodes.objects(), out, usage, true); - } - - void transformExpList(ExpList_t* expList, str_list& out) { - str_list temp; - for (auto exp : expList->exprs.objects()) { - transformExp(static_cast(exp), temp); - } - out.push_back(join(temp, ", "sv)); - } - - void transformExpListLow(ExpListLow_t* expListLow, str_list& out) { - str_list temp; - for (auto exp : expListLow->exprs.objects()) { - transformExp(static_cast(exp), temp); - } - out.push_back(join(temp, ", "sv)); - } - - void transformExp(Exp_t* exp, str_list& out) { - str_list temp; - transformValue(exp->value, temp); - for (auto _opValue : exp->opValues.objects()) { - auto opValue = static_cast(_opValue); - transformBinaryOperator(opValue->op, temp); - transformValue(opValue->value, temp); - } - out.push_back(join(temp, " "sv)); - } - - void transformValue(Value_t* value, str_list& out) { - auto item = value->item.get(); - switch (item->getId()) { - case "SimpleValue"_id: transformSimpleValue(static_cast(item), out); break; - case "simple_table"_id: transform_simple_table(static_cast(item), out); break; - case "ChainValue"_id: { - auto chainValue = static_cast(item); - if (isColonChain(chainValue)) { - transformColonChainClosure(chainValue, out); - } else { - transformChainValue(chainValue, out); - } - break; - } - case "String"_id: transformString(static_cast(item), out); break; - default: break; - } - } - - void transformCallable(Callable_t* callable, str_list& out, bool invoke) { - auto item = callable->item.get(); - switch (item->getId()) { - case "Variable"_id: { - transformVariable(static_cast(item), out); - if (_lintGlobalVar && !isDefined(out.back())) { - if (_globals.find(out.back()) == _globals.end()) { - _globals[out.back()] = {item->m_begin.m_line, item->m_begin.m_col}; - } - } - break; - } - case "SelfName"_id: { transformSelfName(static_cast(item), out, invoke); - if (_lintGlobalVar) { - std::string self("self"sv); - if (!isDefined(self)) { - if (_globals.find(self) == _globals.end()) { - _globals[self] = {item->m_begin.m_line, item->m_begin.m_col}; - } - } - } - break; - } - case "VarArg"_id: out.push_back(s("..."sv)); break; - case "Parens"_id: transformParens(static_cast(item), out); break; - default: break; - } - } - - void transformParens(Parens_t* parans, str_list& out) { - str_list temp; - transformExp(parans->expr, temp); - out.push_back(s("("sv) + temp.front() + s(")"sv)); - } - - void transformSimpleValue(SimpleValue_t* simpleValue, str_list& out) { - auto value = simpleValue->value.get(); - switch (value->getId()) { - case "const_value"_id: transform_const_value(static_cast(value), out); break; - case "If"_id: transformIf(static_cast(value), out, IfUsage::Closure); break; - case "Unless"_id: transformUnless(static_cast(value), out, IfUsage::Closure); break; - case "Switch"_id: transformSwitchClosure(static_cast(value), out); break; - case "With"_id: transformWithClosure(static_cast(value), out); break; - case "ClassDecl"_id: transformClassDeclClosure(static_cast(value), out); break; - case "ForEach"_id: transformForEachClosure(static_cast(value), out); break; - case "For"_id: transformForClosure(static_cast(value), out); break; - case "While"_id: transformWhileClosure(static_cast(value), out); break; - case "Do"_id: transformDoClosure(static_cast(value), out); break; - case "unary_exp"_id: transform_unary_exp(static_cast(value), out); break; - case "TblComprehension"_id: transformTblCompClosure(static_cast(value), out); break; - case "TableLit"_id: transformTableLit(static_cast(value), out); break; - case "Comprehension"_id: transformCompClosure(static_cast(value), out); break; - case "FunLit"_id: transformFunLit(static_cast(value), out); break; - case "Num"_id: transformNum(static_cast(value), out); break; - default: break; - } - } - - void transformFunLit(FunLit_t* funLit, str_list& out) { - str_list temp; - bool isFatArrow = toString(funLit->arrow) == "=>"sv; - pushScope(); - if (isFatArrow) { - forceAddToScope(s("self"sv)); - } - if (auto argsDef = funLit->argsDef.get()) { - transformFnArgsDef(argsDef, temp); - if (funLit->body) { - transformBody(funLit->body, temp, true); - } else { - temp.push_back(Empty); - } - auto it = temp.begin(); - auto& args = *it; - auto& initArgs = *(++it); - auto& bodyCodes = *(++it); - _buf << "function("sv << - (isFatArrow ? s("self, "sv) : Empty) << - args << ')'; - if (!initArgs.empty() || !bodyCodes.empty()) { - _buf << nlr(argsDef) << initArgs << bodyCodes; - popScope(); - _buf << indent() << "end"sv; - } else { - popScope(); - _buf << " end"sv; - } - } else { - if (funLit->body) { - transformBody(funLit->body, temp, true); - } else { - temp.push_back(Empty); - } - auto& bodyCodes = temp.back(); - _buf << "function("sv << - (isFatArrow ? s("self"sv) : Empty) << - ')'; - if (!bodyCodes.empty()) { - _buf << nll(funLit) << bodyCodes; - popScope(); - _buf << indent() << "end"sv; - } else { - popScope(); - _buf << " end"sv; - } - } - out.push_back(clearBuf()); - } - - void transformCodes(const node_container& nodes, str_list& out, bool implicitReturn) { - LocalMode mode = LocalMode::None; - Local_t* any = nullptr, *capital = nullptr; - for (auto node : nodes) { - auto stmt = static_cast(node); - if (auto local = stmt->content.as()) { - if (auto flag = local->name.as()) { - LocalMode newMode = toString(flag) == "*"sv ? LocalMode::Any : LocalMode::Capital; - if (int(newMode) > int(mode)) { - mode = newMode; - } - if (mode == LocalMode::Any) { - if (!any) any = local; - if (!capital) capital = local; - } else { - if (!capital) capital = local; - } - } else { - auto names = local->name.to(); - for (auto name : names->names.objects()) { - local->forceDecls.push_back(toString(name)); - } - } - } else if (mode != LocalMode::None) { - ClassDecl_t* classDecl = nullptr; - if (auto assignment = assignmentFrom(stmt)) { - auto vars = getAssignVars(assignment); - for (const auto& var : vars) { - if (var.empty()) continue; - if (std::isupper(var[0]) && capital) { - capital->decls.push_back(var); - } else if (any) { - any->decls.push_back(var); - } - } - auto info = extractDestructureInfo(assignment); - if (!info.first.empty()) { - for (const auto& destruct : info.first) - for (const auto& item : destruct.items) - if (item.isVariable) { - if (std::isupper(item.name[0]) && capital) { capital->decls.push_back(item.name); - } else if (any) { - any->decls.push_back(item.name); - } - } - } - BLOCK_START - auto assign = assignment->action.as(); - BREAK_IF(!assign); - BREAK_IF(assign->values.objects().size() != 1); - auto exp = ast_cast(assign->values.objects().front()); - BREAK_IF(!exp); - auto value = singleValueFrom(exp); - classDecl = value->getByPath(); - BLOCK_END - } else if (auto expList = expListFrom(stmt)) { - auto value = singleValueFrom(expList); - classDecl = value->getByPath(); - } - if (classDecl) { - if (auto variable = classDecl->name->item.as()) { - auto className = toString(variable); - if (!className.empty()) { - if (std::isupper(className[0]) && capital) { - capital->decls.push_back(className); - } else if (any) { - any->decls.push_back(className); - } - } - } - } - } - } - if (implicitReturn) { - auto last = static_cast(nodes.back()); - auto x = last; - BLOCK_START - auto expList = expListFrom(last); - BREAK_IF(!expList || - (last->appendix && - last->appendix->item.is())); - auto expListLow = x->new_ptr(); - expListLow->exprs.dup(expList->exprs); - auto returnNode = x->new_ptr(); - returnNode->valueList.set(expListLow); - last->content.set(returnNode); - BLOCK_END - } - str_list temp; - for (auto node : nodes) { - transformStatement(static_cast(node), temp); - } - out.push_back(join(temp)); - } - - void transformBody(Body_t* body, str_list& out, bool implicitReturn = false) { - if (auto stmt = body->content.as()) { - transformCodes(node_container{stmt}, out, implicitReturn); - } else { - transformCodes(body->content.to()->statements.objects(), out, implicitReturn); - } - } - - void transformBlock(Block_t* block, str_list& out, bool implicitReturn = true) { - transformCodes(block->statements.objects(), out, implicitReturn); - } - - void transformReturn(Return_t* returnNode, str_list& out) { - if (auto valueList = returnNode->valueList.get()) { - if (auto singleValue = singleValueFrom(valueList)) { - if (auto simpleValue = singleValue->item.as()) { - auto value = simpleValue->value.get(); - switch (value->getId()) { - case "Comprehension"_id: - transformCompReturn(static_cast(value), out); - return; - case "TblComprehension"_id: - transformTblCompReturn(static_cast(value), out); - return; - case "With"_id: - transformWith(static_cast(value), out, nullptr, true); - return; - case "ClassDecl"_id: - transformClassDecl(static_cast(value), out, ExpUsage::Return); - return; - case "Do"_id: - transformDo(static_cast(value), out, true); - return; - case "Switch"_id: - transformSwitch(static_cast(value), out, true); - return; - case "While"_id: - transformWhileInPlace(static_cast(value), out); - return; - case "For"_id: - transformForInPlace(static_cast(value), out); - return; - case "ForEach"_id: - transformForEachInPlace(static_cast(value), out); - return; - case "If"_id: - transformIf(static_cast(value), out, IfUsage::Return); - return; - case "Unless"_id: - transformUnless(static_cast(value), out, IfUsage::Return); - return; - } - } - if (auto chainValue = singleValue->item.as()) { - if (isColonChain(chainValue)) { - transformColonChain(chainValue, out, ExpUsage::Return); - } else { - transformChainValue(chainValue, out, ExpUsage::Return); - } - return; - } - transformValue(singleValue, out); - out.back() = indent() + s("return "sv) + out.back() + nlr(returnNode); - return; - } else { - str_list temp; - transformExpListLow(valueList, temp); - out.push_back(indent() + s("return "sv) + temp.back() + nlr(returnNode)); - } - } else { - out.push_back(indent() + s("return"sv) + nll(returnNode)); - } - } - - void transformFnArgsDef(FnArgsDef_t* argsDef, str_list& out) { - if (!argsDef->defList) { - out.push_back(Empty); - out.push_back(Empty); - } else { - transformFnArgDefList(argsDef->defList, out); - } - if (argsDef->shadowOption) { - transform_outer_var_shadow(argsDef->shadowOption); - } - } - - void transform_outer_var_shadow(outer_var_shadow_t* shadow) { - markVarShadowed(); - if (shadow->varList) { - for (auto name : shadow->varList->names.objects()) { - addToAllowList(toString(name)); - } - } - } - - void transformFnArgDefList(FnArgDefList_t* argDefList, str_list& out) { - auto x = argDefList; - struct ArgItem { - std::string name; - std::string assignSelf; - }; - std::list argItems; - str_list temp; - std::string varNames; - bool assignSelf = false; - for (auto _def : argDefList->definitions.objects()) { - auto def = static_cast(_def); - auto& arg = argItems.emplace_back(); - switch (def->name->getId()) { - case "Variable"_id: arg.name = toString(def->name); break; - case "SelfName"_id: { - assignSelf = true; - auto selfName = static_cast(def->name.get()); - switch (selfName->name->getId()) { - case "self_class_name"_id: { - auto clsName = static_cast(selfName->name.get()); - arg.name = toString(clsName->name); - arg.assignSelf = s("self.__class."sv) + arg.name; - break; - } - case "self_class"_id: - arg.name = "self.__class"sv; - break; - case "self_name"_id: { - - auto sfName = static_cast(selfName->name.get()); - arg.name = toString(sfName->name); - arg.assignSelf = s("self."sv) + arg.name; - break; - } - case "self"_id: - arg.name = "self"sv; - break; - default: break; - } - break; - } - } - forceAddToScope(arg.name); - if (def->defaultValue) { - pushScope(); - auto expList = toAst(arg.name, ExpList, x); - auto assign = x->new_ptr(); - assign->values.push_back(def->defaultValue.get()); - auto assignment = x->new_ptr(); - assignment->expList.set(expList); - assignment->action.set(assign); - transformAssignment(assignment, temp); - popScope(); - _buf << indent() << "if "sv << arg.name << " == nil then"sv << nll(def); - _buf << temp.back(); - _buf << indent() << "end"sv << nll(def); - temp.back() = clearBuf(); - } - if (varNames.empty()) varNames = arg.name; - else varNames.append(s(", "sv) + arg.name); - } - if (argDefList->varArg) { - auto& arg = argItems.emplace_back(); - arg.name = "..."sv; - if (varNames.empty()) varNames = arg.name; - else varNames.append(s(", "sv) + arg.name); - } - std::string initCodes = join(temp); - if (assignSelf) { - auto sjoin = [](const decltype(argItems)& items, int index) { - std::string result; - for (auto it = items.begin(); it != items.end(); ++it) { - if (it->assignSelf.empty()) continue; - if (result.empty()) result = (&it->name)[index]; - else result.append(s(", "sv) + (&it->name)[index]); - } - return result; - }; - std::string sleft = sjoin(argItems, 1); - std::string sright = sjoin(argItems, 0); - initCodes.append(indent() + sleft + s(" = "sv) + sright + nll(argDefList)); - } - out.push_back(varNames); - out.push_back(initCodes); - } - - void transformSelfName(SelfName_t* selfName, str_list& out, bool invoke) { - auto name = selfName->name.get(); - switch (name->getId()) { - case "self_class_name"_id: { - auto clsName = static_cast(name); - out.push_back(s("self.__class"sv) + s(invoke ? ":"sv : "."sv) + toString(clsName->name)); - break; - } - case "self_class"_id: - out.push_back(s("self.__class"sv)); - break; - case "self_name"_id: { - auto sfName = static_cast(name); - out.push_back(s("self"sv) + s(invoke ? ":"sv : "."sv) + toString(sfName->name)); - break; - } - case "self"_id: - out.push_back(s("self"sv)); - break; - } - } - - void transformColonChainClosure(ChainValue_t* chainValue, str_list& out) { - str_list temp; - temp.push_back(s("(function()"sv) + nll(chainValue)); - pushScope(); - transformColonChain(chainValue, temp, ExpUsage::Return); - popScope(); - temp.push_back(indent() + s("end)()"sv)); - out.push_back(join(temp)); - } - - void transformColonChain(ChainValue_t* chainValue, str_list& out, ExpUsage usage = ExpUsage::Common, ExpList_t* expList = nullptr) { - auto x = chainValue; - const auto& chainList = chainValue->items.objects(); - auto baseChain = x->new_ptr(); - switch (chainList.front()->getId()) { - case "DotChainItem"_id: - case "ColonChainItem"_id: - if (_withVars.empty()) { - throw std::logic_error(debugInfo("Short dot/colon syntax must be called within a with block."sv, chainList.front())); - } else { - baseChain->items.push_back(toAst(_withVars.top(), Callable, x)); - } - break; - } - auto end = --chainList.end(); - for (auto it = chainList.begin(); it != end; ++it) { - baseChain->items.push_back(*it); - } - auto colonChainItem = static_cast(chainList.back()); - auto funcName = toString(colonChainItem->name); - if (usage != ExpUsage::Return) pushScope(); - auto baseVar = getUnusedName("_base_"sv); - auto fnVar = getUnusedName("_fn_"sv); - str_list temp; - { - auto value = x->new_ptr(); - value->item.set(baseChain); - auto exp = x->new_ptr(); - exp->value.set(value); - auto assign = x->new_ptr(); - assign->values.push_back(exp); - auto assignment = x->new_ptr(); - assignment->expList.set(toAst(baseVar, ExpList, x)); - assignment->action.set(assign); - transformAssignment(assignment, temp); - } - { - auto assign = x->new_ptr(); - assign->values.push_back(toAst(baseVar + "." + funcName, Exp, x)); - auto assignment = x->new_ptr(); - assignment->expList.set(toAst(fnVar, ExpList, x)); - assignment->action.set(assign); - transformAssignment(assignment, temp); - } - auto funLit = toAst(s("(...)-> "sv) + fnVar + s(" "sv) + baseVar + s(", ..."sv), Exp, x); - switch (usage) { - case ExpUsage::Return: - transformExp(funLit, temp); - _buf << temp.front(); - _buf << *(++temp.begin()); - _buf << indent() << "return " << temp.back() << nll(chainValue); - break; - case ExpUsage::Assignment: { - auto assign = x->new_ptr(); - assign->values.push_back(funLit); - auto assignment = x->new_ptr(); - assignment->expList.set(expList); - assignment->action.set(assign); - transformAssignment(assignment, temp); - _buf << indent(-1) << "do"sv << nll(chainValue); - _buf << temp.front(); - _buf << *(++temp.begin()); - _buf << temp.back(); - popScope(); - _buf << indent() << "end"sv << nll(chainValue); - break; - } - case ExpUsage::Common: { - auto assign = x->new_ptr(); - assign->values.push_back(funLit); - auto assignment = x->new_ptr(); - assignment->expList.set(toAst("_"sv, ExpList, x)); - assignment->action.set(assign); - transformAssignment(assignment, temp); - _buf << indent(-1) << "do"sv << nll(chainValue); - _buf << temp.front(); - _buf << *(++temp.begin()); - _buf << temp.back(); - popScope(); - _buf << indent() << "end"sv << nll(chainValue); - break; - } - default: break; - } - out.push_back(clearBuf()); - } - - void transformChainList(const node_container& chainList, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) { - auto x = chainList.front(); - str_list temp; - switch (chainList.front()->getId()) { - case "DotChainItem"_id: - case "ColonChainItem"_id: - if (_withVars.empty()) { - throw std::logic_error(debugInfo("Short dot/colon syntax must be called within a with block."sv, chainList.front())); - } else { - temp.push_back(_withVars.top()); - } - break; - } - for (auto it = chainList.begin(); it != chainList.end(); ++it) { - auto item = *it; - switch (item->getId()) { - case "Invoke"_id: - transformInvoke(static_cast(item), temp); - break; - case "DotChainItem"_id: - transformDotChainItem(static_cast(item), temp); - break; - case "ColonChainItem"_id: { - auto colonItem = static_cast(item); - auto next = it; ++next; - auto followItem = next != chainList.end() ? *next : nullptr; - if (!ast_is(followItem)) { - throw std::logic_error(debugInfo("Colon chain item must be followed by invoke arguments."sv, colonItem)); - } - if (colonItem->name.is()) { - auto callVar = getUnusedName(s("_call_"sv)); - auto block = x->new_ptr(); - { - auto chainValue = x->new_ptr(); - switch (chainList.front()->getId()) { - case "DotChainItem"_id: - case "ColonChainItem"_id: - chainValue->items.push_back(toAst(_withVars.top(), Callable, x)); - break; - } - for (auto i = chainList.begin(); i != it; ++i) { - chainValue->items.push_back(*i); - } - auto value = x->new_ptr(); - value->item.set(chainValue); - auto exp = x->new_ptr(); - exp->value.set(value); - auto assignment = x->new_ptr(); - assignment->expList.set(toAst(callVar, ExpList, x)); - auto assign = x->new_ptr(); - assign->values.push_back(exp); - assignment->action.set(assign); - auto stmt = x->new_ptr(); - stmt->content.set(assignment); - block->statements.push_back(stmt); - } - { - auto name = toString(colonItem->name); - auto chainValue = x->new_ptr(); - chainValue->items.push_back(toAst(callVar, Callable, x)); - chainValue->items.push_back(toAst(s("\""sv) + name + s("\""sv), Exp, x)); - if (auto invoke = ast_cast(followItem)) { - invoke->args.push_front(toAst(callVar, Exp, x)); - } else { - auto invokeArgs = static_cast(followItem); - invokeArgs->args.push_front(toAst(callVar, Exp, x)); - } - chainValue->items.push_back(followItem); - for (auto i = ++next; i != chainList.end(); ++i) { - chainValue->items.push_back(*i); - } - auto value = x->new_ptr(); - value->item.set(chainValue); - auto exp = x->new_ptr(); - exp->value.set(value); - auto expList = x->new_ptr(); - expList->exprs.push_back(exp); - auto expListAssign = x->new_ptr(); - expListAssign->expList.set(expList); - auto stmt = x->new_ptr(); - stmt->content.set(expListAssign); - block->statements.push_back(stmt); - } - switch (usage) { - case ExpUsage::Common: - transformBlock(block, out, false); - return; - case ExpUsage::Return: - transformBlock(block, out, true); - return; - case ExpUsage::Assignment: { - auto body = x->new_ptr(); - body->content.set(block); - assignLastExplist(assignList, body); - transformBlock(block, out); - return; - } - default: - break; - } - auto body = x->new_ptr(); - body->content.set(block); - auto funLit = toAst("->"sv, FunLit, x); - funLit->body.set(body); - auto simpleValue = x->new_ptr(); - simpleValue->value.set(funLit); - auto value = x->new_ptr(); - value->item.set(simpleValue); - auto exp = x->new_ptr(); - exp->value.set(value); - auto paren = x->new_ptr(); - paren->expr.set(exp); - auto callable = x->new_ptr(); - callable->item.set(paren); - auto chainValue = x->new_ptr(); - chainValue->items.push_back(callable); - auto invoke = x->new_ptr(); - chainValue->items.push_back(invoke); - transformChainValue(chainValue, out); - return; - } - transformColonChainItem(colonItem, temp); - break; - } - case "Slice"_id: - transformSlice(static_cast(item), temp); - break; - case "Callable"_id: { - auto next = it; ++next; - auto followItem = next != chainList.end() ? *next : nullptr; - transformCallable(static_cast(item), temp, - followItem && ast_is(followItem)); - break; - } - case "String"_id: - transformString(static_cast(item), temp); - temp.back() = s("("sv) + temp.back() + s(")"sv); - break; - case "Exp"_id: - transformExp(static_cast(item), temp); - temp.back() = s("["sv) + temp.back() + s("]"sv); - break; - case "InvokeArgs"_id: transformInvokeArgs(static_cast(item), temp); break; - default: break; - } - } - switch (usage) { - case ExpUsage::Common: - out.push_back(indent() + join(temp) + nll(chainList.front())); - break; - case ExpUsage::Return: - out.push_back(indent() + s("return "sv) + join(temp) + nll(chainList.front())); - break; - default: - out.push_back(join(temp)); - break; - } - } - - void transformChainValue(ChainValue_t* chainValue, str_list& out, ExpUsage usage = ExpUsage::Closure, ExpList_t* assignList = nullptr) { - transformChainList(chainValue->items.objects(), out, usage, assignList); - } - - void transformAssignableChain(AssignableChain_t* chain, str_list& out) { - transformChainList(chain->items.objects(), out, ExpUsage::Closure); - } - - void transformDotChainItem(DotChainItem_t* dotChainItem, str_list& out) { - auto name = toString(dotChainItem->name); - if (State::keywords.find(name) != State::keywords.end()) { - out.push_back(s("[\""sv) + name + s("\"]"sv)); - } else { - out.push_back(s("."sv) + name); - } - } - - void transformColonChainItem(ColonChainItem_t* colonChainItem, str_list& out) { - auto name = toString(colonChainItem->name); - out.push_back(s(colonChainItem->switchToDot ? "."sv : ":"sv) + name); - } - - void transformSlice(Slice_t* slice, str_list& out) { - throw std::logic_error(debugInfo("Slice syntax not supported here."sv, slice)); - } - - void transformInvoke(Invoke_t* invoke, str_list& out) { - str_list temp; - for (auto arg : invoke->args.objects()) { - switch (arg->getId()) { - case "Exp"_id: transformExp(static_cast(arg), temp); break; - case "SingleString"_id: transformSingleString(static_cast(arg), temp); break; - case "DoubleString"_id: transformDoubleString(static_cast(arg), temp); break; - case "LuaString"_id: transformLuaString(static_cast(arg), temp); break; - default: break; - } - } - out.push_back(s("("sv) + join(temp, ", "sv) + s(")"sv)); - } - - void transform_unary_exp(unary_exp_t* unary_exp, str_list& out) { - std::string op = toString(unary_exp->m_begin.m_it, unary_exp->item->m_begin.m_it); - str_list temp{op + (op == "not"sv ? s(" "sv) : Empty)}; - transformExp(unary_exp->item, temp); - out.push_back(join(temp)); - } - - void transformVariable(Variable_t* name, str_list& out) { - out.push_back(toString(name)); - } - - void transformNum(Num_t* num, str_list& out) { - out.push_back(toString(num)); - } - - void transformTableLit(TableLit_t* table, str_list& out) { - transformTable(table, table->values.objects(), out); - } - - void transformCompCommon(Comprehension_t* comp, str_list& out) { - str_list temp; - auto x = comp; - auto compInner = comp->forLoop.get(); - for (auto item : compInner->items.objects()) { - switch (item->getId()) { - case "CompForEach"_id: - transformCompForEach(static_cast(item), temp); - break; - case "CompFor"_id: - transformCompFor(static_cast(item), temp); - break; - case "Exp"_id: - transformExp(static_cast(item), temp); - temp.back() = indent() + s("if "sv) + temp.back() + s(" then"sv) + nll(item); - pushScope(); - break; - } - } - if (auto stmt = comp->value.as()) { - transformStatement(stmt, temp); - } else if (auto exp = comp->value.as()) { - auto expList = x->new_ptr(); - expList->exprs.push_back(exp); - auto expListAssign = x->new_ptr(); - expListAssign->expList.set(expList); - auto statement = x->new_ptr(); - statement->content.set(expListAssign); - transformStatement(statement, temp); - } - auto value = temp.back(); - temp.pop_back(); - _buf << join(temp) << value; - for (size_t i = 0; i < compInner->items.objects().size(); ++i) { - popScope(); - _buf << indent() << "end"sv << nll(comp); - } - out.push_back(clearBuf()); - } - - void transformComprehension(Comprehension_t* comp, str_list& out) { - str_list temp; - std::string accum = getUnusedName("_accum_"); - std::string len = getUnusedName("_len_"); - addToScope(accum); - addToScope(len); - auto compInner = comp->forLoop.get(); - for (auto item : compInner->items.objects()) { - switch (item->getId()) { - case "CompForEach"_id: - transformCompForEach(static_cast(item), temp); - break; - case "CompFor"_id: - transformCompFor(static_cast(item), temp); - break; - case "Exp"_id: - transformExp(static_cast(item), temp); - temp.back() = indent() + s("if "sv) + temp.back() + s(" then"sv) + nll(item); - pushScope(); - break; - } - } - transformExp(comp->value.to(), temp); - auto value = temp.back(); - temp.pop_back(); - for (size_t i = 0; i < compInner->items.objects().size(); ++i) { - popScope(); - } - _buf << indent() << "local "sv << accum << " = { }"sv << nll(comp); - _buf << indent() << "local "sv << len << " = 1"sv << nll(comp); - _buf << join(temp); - _buf << indent(int(temp.size())) << accum << "["sv << len << "] = "sv << value << nll(comp); - _buf << indent(int(temp.size())) << len << " = "sv << len << " + 1"sv << nll(comp); - for (int ind = int(temp.size()) - 1; ind > -1 ; --ind) { - _buf << indent(ind) << "end"sv << nll(comp); - } - out.push_back(accum); - out.push_back(clearBuf()); - } - - void transformCompInPlace(Comprehension_t* comp, ExpList_t* expList, str_list& out) { - auto x = comp; - str_list temp; - auto ind = indent(); - pushScope(); - transformComprehension(comp, temp); - auto assign = x->new_ptr(); - assign->values.push_back(toAst(temp.front(), Exp, x)); - auto assignment = x->new_ptr(); - assignment->expList.set(expList); - assignment->action.set(assign); - transformAssignment(assignment, temp); - out.push_back( - ind + s("do"sv) + nll(comp) + - *(++temp.begin()) + - temp.back()); - popScope(); - out.back() = out.back() + indent() + s("end"sv) + nlr(comp); - } - - void transformCompReturn(Comprehension_t* comp, str_list& out) { - str_list temp; - transformComprehension(comp, temp); - out.push_back(temp.back() + indent() + s("return "sv) + temp.front() + nlr(comp)); - } - - void transformCompClosure(Comprehension_t* comp, str_list& out) { - str_list temp; - std::string before = s("(function()"sv) + nll(comp); - pushScope(); - transformComprehension(comp, temp); - out.push_back( - before + - temp.back() + - indent() + s("return "sv) + temp.front() + nlr(comp)); - popScope(); - out.back() = out.back() + indent() + s("end)()"sv); - } - - void transformForEachHead(AssignableNameList_t* nameList, ast_node* loopTarget, str_list& out) { - auto x = nameList; - str_list temp; - str_list vars; - str_list varBefore, varAfter; - std::list>> destructPairs; - for (auto _item : nameList->items.objects()) { - auto item = static_cast(_item)->item.get(); - switch (item->getId()) { - case "Variable"_id: - transformVariable(static_cast(item), vars); - varAfter.push_back(vars.back()); - break; - case "TableLit"_id: { - auto desVar = getUnusedName("_des_"sv); - destructPairs.emplace_back(item, toAst(desVar, Exp, x)); - vars.push_back(desVar); - varAfter.push_back(desVar); - break; - } - default: break; - } - } - switch (loopTarget->getId()) { - case "star_exp"_id: { - auto star_exp = static_cast(loopTarget); - auto listVar = singleVariableFrom(star_exp->value); - auto indexVar = getUnusedName("_index_"); - varAfter.push_back(indexVar); - auto value = singleValueFrom(star_exp->value); - if (!value) throw std::logic_error(debugInfo("Invalid star syntax."sv, star_exp)); - bool endWithSlice = false; - BLOCK_START - auto chainValue = value->item.as(); - BREAK_IF(!chainValue); - auto chainList = chainValue->items.objects(); - auto slice = ast_cast(chainList.back()); - BREAK_IF(!slice); - endWithSlice = true; - if (listVar.empty() && chainList.size() == 2 && - ast_is(chainList.front())) { - transformCallable(static_cast(chainList.front()), temp, false); - listVar = temp.back(); - temp.pop_back(); - } - chainList.pop_back(); - auto chain = x->new_ptr(); - for (auto item : chainList) { - chain->items.push_back(item); - } - std::string startValue("1"sv); - if (auto exp = slice->startValue.as()) { - transformExp(exp, temp); - startValue = temp.back(); - temp.pop_back(); - } - std::string stopValue; - if (auto exp = slice->stopValue.as()) { - transformExp(exp, temp); - stopValue = temp.back(); - temp.pop_back(); - } - std::string stepValue; - if (auto exp = slice->stepValue.as()) { - transformExp(exp, temp); - stepValue = temp.back(); - temp.pop_back(); - } - if (listVar.empty()) { - listVar = getUnusedName("_list_"); - varBefore.push_back(listVar); - transformChainValue(chain, temp); - _buf << indent() << "local "sv << listVar << " = "sv << temp.back() << nll(nameList); - } - std::string maxVar; - if (!stopValue.empty()) { - maxVar = getUnusedName("_max_"); - varBefore.push_back(maxVar); - _buf << indent() << "local "sv << maxVar << " = "sv << stopValue << nll(nameList); - } - _buf << indent() << "for "sv << indexVar << " = "sv; - _buf << startValue << ", "sv; - if (stopValue.empty()) { - _buf << "#"sv << listVar; - } else { - _buf << maxVar << " < 0 and #"sv << listVar <<" + " << maxVar << " or "sv << maxVar; - } - if (!stepValue.empty()) { - _buf << ", "sv << stepValue; - } - _buf << " do"sv << nlr(loopTarget); - _buf << indent(1) << "local "sv << join(vars, ", "sv) << " = "sv << listVar << "["sv << indexVar << "]"sv << nll(nameList); - out.push_back(clearBuf()); - BLOCK_END - bool newListVal = false; - if (listVar.empty()) { - newListVal = true; - listVar = getUnusedName("_list_"); - varBefore.push_back(listVar); - } - if (!endWithSlice) { - transformExp(star_exp->value, temp); - if (newListVal) _buf << indent() << "local "sv << listVar << " = "sv << temp.back() << nll(nameList); - _buf << indent() << "for "sv << indexVar << " = 1, #"sv << listVar << " do"sv << nlr(loopTarget); - _buf << indent(1) << "local "sv << join(vars) << " = "sv << listVar << "["sv << indexVar << "]"sv << nll(nameList); - out.push_back(clearBuf()); - } - break; - } - case "Exp"_id: - transformExp(static_cast(loopTarget), temp); - _buf << indent() << "for "sv << join(vars, ", "sv) << " in "sv << temp.back() << " do"sv << nlr(loopTarget); - out.push_back(clearBuf()); - break; - case "ExpList"_id: - transformExpList(static_cast(loopTarget), temp); - _buf << indent() << "for "sv << join(vars, ", "sv) << " in "sv << temp.back() << " do"sv << nlr(loopTarget); - out.push_back(clearBuf()); - break; - default: break; - } - for (auto& var : varBefore) addToScope(var); - pushScope(); - for (auto& var : varAfter) addToScope(var); - if (!destructPairs.empty()) { - temp.clear(); - for (auto& pair : destructPairs) { - auto sValue = x->new_ptr(); - sValue->value.set(pair.first); - auto value = x->new_ptr(); - value->item.set(sValue); - auto exp = x->new_ptr(); - exp->value.set(value); - auto expList = x->new_ptr(); - expList->exprs.push_back(exp); - auto assign = x->new_ptr(); - assign->values.push_back(pair.second); - auto assignment = x->new_ptr(); - assignment->expList.set(expList); - assignment->action.set(assign); - transformAssignment(assignment, temp); - } - out.back().append(join(temp)); - } - } - - void transformCompForEach(CompForEach_t* comp, str_list& out) { - transformForEachHead(comp->nameList, comp->loopValue, out); - } - - void transformInvokeArgs(InvokeArgs_t* invokeArgs, str_list& out) { - str_list temp; - for (auto arg : invokeArgs->args.objects()) { - switch (arg->getId()) { - case "Exp"_id: transformExp(static_cast(arg), temp); break; - case "TableBlock"_id: transformTableBlock(static_cast(arg), temp); break; - default: break; - } - } - out.push_back(s("("sv) + join(temp, ", "sv) + s(")"sv)); - } - - void transformForHead(For_t* forNode, str_list& out) { - str_list temp; - std::string varName = toString(forNode->varName); - transformExp(forNode->startValue, temp); - transformExp(forNode->stopValue, temp); - if (forNode->stepValue) { - transformExp(forNode->stepValue->value, temp); - } else { - temp.emplace_back(); - } - auto it = temp.begin(); - const auto& start = *it; - const auto& stop = *(++it); - const auto& step = *(++it); - _buf << indent() << "for "sv << varName << " = "sv << start << ", "sv << stop << (step.empty() ? Empty : s(", "sv) + step) << " do"sv << nll(forNode); - pushScope(); - addToScope(varName); - out.push_back(clearBuf()); - } - - void transformLoopBody(Body_t* body, str_list& out, const std::string& appendContent) { - str_list temp; - bool withContinue = traversal::Stop == body->traverse([&](ast_node* node) { - switch (node->getId()) { - case "For"_id: - case "ForEach"_id: - return traversal::Return; - case "BreakLoop"_id: { - return toString(node) == "continue"sv ? - traversal::Stop : traversal::Return; - } - default: - return traversal::Continue; - } - }); - if (withContinue) { - auto continueVar = getUnusedName("_continue_"sv); - addToScope(continueVar); - _buf << indent() << "local "sv << continueVar << " = false"sv << nll(body); - _buf << indent() << "repeat"sv << nll(body); - temp.push_back(clearBuf()); - _continueVars.push(continueVar); - pushScope(); - } - transformBody(body, temp); - if (withContinue) { - if (!appendContent.empty()) { - _buf << indent() << appendContent; - } - _buf << indent() << _continueVars.top() << " = true"sv << nll(body); - popScope(); - _buf << indent() << "until true"sv << nlr(body); - _buf << indent() << "if not "sv << _continueVars.top() << " then"sv << nlr(body); - _buf << indent(1) << "break"sv << nlr(body); - _buf << indent() << "end"sv << nlr(body); - temp.push_back(clearBuf()); - _continueVars.pop(); - } else if (!appendContent.empty()) { - temp.back().append(indent() + appendContent); - } - out.push_back(join(temp)); - } - - void transformFor(For_t* forNode, str_list& out) { - str_list temp; - transformForHead(forNode, temp); - transformLoopBody(forNode->body, temp, Empty); - popScope(); - out.push_back(join(temp) + indent() + s("end"sv) + nlr(forNode)); - } - - std::string transformForInner(For_t* forNode, str_list& out) { - auto x = forNode; - std::string accum = getUnusedName("_accum_"); - addToScope(accum); - std::string len = getUnusedName("_len_"); - addToScope(len); - _buf << indent() << "local "sv << accum << " = { }"sv << nll(forNode); - _buf << indent() << "local "sv << len << " = 1"sv << nll(forNode); - out.push_back(clearBuf()); - transformForHead(forNode, out); - auto expList = toAst(accum + s("["sv) + len + s("]"sv), ExpList, x); - assignLastExplist(expList, forNode->body); - auto lenLine = len + s(" = "sv) + len + s(" + 1"sv) + nlr(forNode->body); - transformLoopBody(forNode->body, out, lenLine); - popScope(); - out.push_back(indent() + s("end"sv) + nlr(forNode)); - return accum; - } - - void transformForClosure(For_t* forNode, str_list& out) { - str_list temp; - _buf << "(function()"sv << nll(forNode); - pushScope(); - auto accum = transformForInner(forNode, temp); - temp.push_back(indent() + s("return "sv) + accum + nlr(forNode)); - popScope(); - temp.push_back(indent() + s("end)()"sv)); - out.push_back(join(temp)); - } - - void transformForInPlace(For_t* forNode, str_list& out, ExpList_t* assignExpList = nullptr) { - auto x = forNode; - str_list temp; - if (assignExpList) { - _buf << indent() << "do"sv << nll(forNode); - pushScope(); - auto accum = transformForInner(forNode, temp); - auto assign = x->new_ptr(); - assign->values.push_back(toAst(accum, Exp, x)); - auto assignment = x->new_ptr(); - assignment->expList.set(assignExpList); - assignment->action.set(assign); - transformAssignment(assignment, temp); - popScope(); - temp.push_back(indent() + s("end"sv) + nlr(forNode)); - } else { - auto accum = transformForInner(forNode, temp); - auto returnNode = x->new_ptr(); - auto expListLow = toAst(accum, ExpListLow, x); - returnNode->valueList.set(expListLow); - transformReturn(returnNode, temp); - } - out.push_back(join(temp)); - } - - void transformBinaryOperator(BinaryOperator_t* node, str_list& out) { - auto op = toString(node); - out.push_back(op == "!="sv ? s("~="sv) : op); - } - - void transformForEach(ForEach_t* forEach, str_list& out) { - str_list temp; - transformForEachHead(forEach->nameList, forEach->loopValue, temp); - transformLoopBody(forEach->body, temp, Empty); - popScope(); - out.push_back(temp.front() + temp.back() + indent() + s("end"sv) + nlr(forEach)); - } - - std::string transformForEachInner(ForEach_t* forEach, str_list& out) { - auto x = forEach; - std::string accum = getUnusedName("_accum_"); - addToScope(accum); - std::string len = getUnusedName("_len_"); - addToScope(len); - _buf << indent() << "local "sv << accum << " = { }"sv << nll(forEach); - _buf << indent() << "local "sv << len << " = 1"sv << nll(forEach); - out.push_back(clearBuf()); - transformForEachHead(forEach->nameList, forEach->loopValue, out); - auto expList = toAst(accum + s("["sv) + len + s("]"sv), ExpList, x); - assignLastExplist(expList, forEach->body); - auto lenLine = len + s(" = "sv) + len + s(" + 1"sv) + nlr(forEach->body); - transformLoopBody(forEach->body, out, lenLine); - popScope(); - out.push_back(indent() + s("end"sv) + nlr(forEach)); - return accum; - } - - void transformForEachClosure(ForEach_t* forEach, str_list& out) { - str_list temp; - _buf << "(function()"sv << nll(forEach); - pushScope(); - auto accum = transformForEachInner(forEach, temp); - temp.push_back(indent() + s("return "sv) + accum + nlr(forEach)); - popScope(); - temp.push_back(indent() + s("end)()"sv)); - out.push_back(join(temp)); - } - - void transformForEachInPlace(ForEach_t* forEach, str_list& out, ExpList_t* assignExpList = nullptr) { - auto x = forEach; - str_list temp; - if (assignExpList) { - _buf << indent() << "do"sv << nll(forEach); - pushScope(); - auto accum = transformForEachInner(forEach, temp); - auto assign = x->new_ptr(); - assign->values.push_back(toAst(accum, Exp, x)); - auto assignment = x->new_ptr(); - assignment->expList.set(assignExpList); - assignment->action.set(assign); - transformAssignment(assignment, temp); - popScope(); - temp.push_back(indent() + s("end"sv) + nlr(forEach)); - } else { - auto accum = transformForEachInner(forEach, temp); - auto returnNode = x->new_ptr(); - auto expListLow = toAst(accum, ExpListLow, x); - returnNode->valueList.set(expListLow); - transformReturn(returnNode, temp); - } - out.push_back(join(temp)); - } - - void transform_variable_pair(variable_pair_t* pair, str_list& out) { - auto name = toString(pair->name); - out.push_back(name + s(" = "sv) + name); - } - - void transform_normal_pair(normal_pair_t* pair, str_list& out) { - auto key = pair->key.get(); - str_list temp; - switch (key->getId()) { - case "KeyName"_id: { - transformKeyName(static_cast(key), temp); - if (State::luaKeywords.find(temp.back()) != State::luaKeywords.end()) { - temp.back() = s("[\""sv) + temp.back() + s("\"]"); - } - break; - } - case "Exp"_id: - transformExp(static_cast(key), temp); - temp.back() = s("["sv) + temp.back() + s("]"sv); - break; - case "DoubleString"_id: - transformDoubleString(static_cast(key), temp); - temp.back() = s("["sv) + temp.back() + s("]"sv); - break; - case "SingleString"_id: transformSingleString(static_cast(key), temp); - temp.back() = s("["sv) + temp.back() + s("]"sv); - break; - default: break; - } - auto value = pair->value.get(); - switch (value->getId()) { - case "Exp"_id: transformExp(static_cast(value), temp); break; - case "TableBlock"_id: transformTableBlock(static_cast(value), temp); break; - default: break; - } - out.push_back(temp.front() + s(" = "sv) + temp.back()); - } - - void transformKeyName(KeyName_t* keyName, str_list& out) { - auto name = keyName->name.get(); - switch (name->getId()) { - case "SelfName"_id: transformSelfName(static_cast(name), out, false); break; - case "Name"_id: out.push_back(toString(name)); break; - default: break; - } - } - - void replace(std::string& str, std::string_view from, std::string_view to) { - size_t start_pos = 0; - while((start_pos = str.find(from, start_pos)) != std::string::npos) { - str.replace(start_pos, from.size(), to); - start_pos += to.size(); - } - } - - void transformLuaString(LuaString_t* luaString, str_list& out) { - auto content = toString(luaString->content); - replace(content, "\r"sv, ""); - if (content[0] == '\n') content.erase(content.begin()); - out.push_back(toString(luaString->open) + content + toString(luaString->close)); - } - - void transformSingleString(SingleString_t* singleString, str_list& out) { - auto str = toString(singleString); - replace(str, "\r"sv, ""); - replace(str, "\n"sv, "\\n"sv); - out.push_back(str); - } - - void transformDoubleString(DoubleString_t* doubleString, str_list& out) { - str_list temp; - for (auto _seg : doubleString->segments.objects()) { - auto seg = static_cast(_seg); - auto content = seg->content.get(); - switch (content->getId()) { - case "double_string_inner"_id: { - auto str = toString(content); - replace(str, "\r"sv, ""); - replace(str, "\n"sv, "\\n"sv); - temp.push_back(s("\""sv) + str + s("\""sv)); - break; - } - case "Exp"_id: - transformExp(static_cast(content), temp); - temp.back() = s("tostring("sv) + temp.back() + s(")"sv); - break; - default: break; - } - } - out.push_back(temp.empty() ? s("\"\""sv) : join(temp, " .. "sv)); - } - - void transformString(String_t* string, str_list& out) { - auto str = string->str.get(); - switch (str->getId()) { - case "SingleString"_id: transformSingleString(static_cast(str), out); break; - case "DoubleString"_id: transformDoubleString(static_cast(str), out); break; - case "LuaString"_id: transformLuaString(static_cast(str), out); break; - default: break; - } - } - - std::pair defineClassVariable(Assignable_t* assignable) { - if (auto variable = assignable->item.as()) { - auto name = toString(variable); - if (addToScope(name)) { - return {name, true}; - } else { - return {name, false}; - } - } - return {Empty, false}; - } - - void transformClassDeclClosure(ClassDecl_t* classDecl, str_list& out) { - str_list temp; - temp.push_back(s("(function()"sv) + nll(classDecl)); - pushScope(); - transformClassDecl(classDecl, temp, ExpUsage::Return); - popScope(); - temp.push_back(s("end)()"sv)); - out.push_back(join(temp)); - } - - void transformClassDecl(ClassDecl_t* classDecl, str_list& out, ExpUsage usage = ExpUsage::Common, ExpList_t* expList = nullptr) { - str_list temp; - auto x = classDecl; - auto body = classDecl->body.get(); - auto assignable = classDecl->name.get(); - auto extend = classDecl->extend.get(); - std::string className; - std::string assignItem; - if (assignable) { - if (!isAssignable(assignable)) { - throw std::logic_error(debugInfo("Left hand expression is not assignable."sv, assignable)); - } - bool newDefined = false; - std::tie(className, newDefined) = defineClassVariable(assignable); - if (newDefined) { - temp.push_back(indent() + s("local "sv) + className + nll(classDecl)); - } - if (className.empty()) { - if (auto chain = ast_cast(assignable->item)) { - if (auto dotChain = ast_cast(chain->items.back())) { - className = s("\""sv) + toString(dotChain->name) + s("\""sv); - } else if (auto index = ast_cast(chain->items.back())) { - if (auto name = index->getByPath()) { - transformString(name, temp); - className = temp.back(); - temp.pop_back(); - } - } - } - } else { - className = s("\""sv) + className + s("\""sv); - } - pushScope(); - transformAssignable(assignable, temp); - popScope(); - assignItem = temp.back(); - temp.pop_back(); - } else if (expList) { - auto name = singleVariableFrom(expList); - if (!name.empty()) { - className = s("\""sv) + name + s("\""sv); - } - } - temp.push_back(indent() + s("do"sv) + nll(classDecl)); - pushScope(); - auto classVar = getUnusedName("_class_"sv); - addToScope(classVar); - temp.push_back(indent() + s("local "sv) + classVar + nll(classDecl)); - if (body) { - str_list varDefs; - for (auto item : body->contents.objects()) { - if (auto statement = ast_cast(item)) { - ClassDecl_t* clsDecl = nullptr; - if (auto assignment = assignmentFrom(statement)) { - auto names = transformAssignDefs(assignment->expList.get()); - varDefs.insert(varDefs.end(), names.begin(), names.end()); - auto info = extractDestructureInfo(assignment); - if (!info.first.empty()) { - for (const auto& destruct : info.first) - for (const auto& item : destruct.items) - if (item.isVariable && addToScope(item.name)) - varDefs.push_back(item.name); - } - BLOCK_START - auto assign = assignment->action.as(); - BREAK_IF(!assign); - BREAK_IF(assign->values.objects().size() != 1); - auto exp = ast_cast(assign->values.objects().front()); - BREAK_IF(!exp); - auto value = singleValueFrom(exp); - clsDecl = value->getByPath(); - BLOCK_END - } else if (auto expList = expListFrom(statement)) { - auto value = singleValueFrom(expList); - clsDecl = value->getByPath(); - } - if (clsDecl) { - std::string clsName; - bool newDefined = false; - std::tie(clsName,newDefined) = defineClassVariable(clsDecl->name); - if (newDefined) varDefs.push_back(clsName); - } - } - } - if (!varDefs.empty()) { - temp.push_back(indent() + s("local ") + join(varDefs, ", "sv) + nll(body)); - } - } - std::string parent, parentVar; - if (extend) { - parentVar = getUnusedName("_parent_"sv); - addToScope(parentVar); - transformExp(extend, temp); - parent = temp.back(); - temp.pop_back(); - temp.push_back(indent() + s("local "sv) + parentVar + s(" = "sv) + parent + nll(classDecl)); - } - auto baseVar = getUnusedName("_base_"sv); - addToScope(baseVar); - temp.push_back(indent() + s("local "sv) + baseVar + s(" = "sv)); - str_list builtins; - str_list commons; - str_list statements; - if (body) { - std::list members; - for (auto content : classDecl->body->contents.objects()) { - switch (content->getId()) { - case "class_member_list"_id: { - size_t inc = transform_class_member_list(static_cast(content), members, classVar); - auto it = members.end(); - for (size_t i = 0; i < inc; ++i, --it); - for (; it != members.end(); ++it) { - auto& member = *it; - if (member.type == MemType::Property) { - statements.push_back(indent() + member.item + nll(content)); - } else { - member.item = indent(1) + member.item; - } - } - break; - } - case "Statement"_id: - transformStatement(static_cast(content), statements); - break; - default: break; - } - } - for (auto& member : members) { - switch (member.type) { - case MemType::Common: - commons.push_back((commons.empty() ? Empty : s(","sv) + nll(member.node)) + member.item); - break; - case MemType::Builtin: - builtins.push_back((builtins.empty() ? Empty : s(","sv) + nll(member.node)) + member.item); - break; - default: break; - } - } - if (!commons.empty()) { - temp.back() += s("{"sv) + nll(body); - temp.push_back(join(commons) + nll(body)); - temp.push_back(indent() + s("}"sv) + nll(body)); - } else { - temp.back() += s("{ }"sv) + nll(body); - } - } else { - temp.back() += s("{ }"sv) + nll(classDecl); - } - temp.push_back(indent() + baseVar + s(".__index = "sv) + baseVar + nll(classDecl)); - str_list tmp; - if (usage == ExpUsage::Assignment) { - auto assign = x->new_ptr(); - assign->values.push_back(toAst(classVar, Exp, x)); - auto assignment = x->new_ptr(); - assignment->expList.set(expList); - assignment->action.set(assign); - transformAssignment(assignment, tmp); - } - if (extend) { - _buf << indent() << "setmetatable("sv << baseVar << ", "sv << parentVar << ".__base)"sv << nll(classDecl); - } - _buf << indent() << classVar << " = setmetatable({" << nll(classDecl); - if (!builtins.empty()) { - _buf << join(builtins) << ","sv << nll(classDecl); - } else { - if (extend) { - _buf << indent(1) << "__init = function(self, ...)"sv << nll(classDecl); - _buf << indent(2) << "return _class_0.__parent.__init(self, ...)"sv << nll(classDecl); - _buf << indent(1) << "end,"sv << nll(classDecl); - } else { - _buf << indent(1) << "__init = function() end,"sv << nll(classDecl); - } - } - _buf << indent(1) << "__base = "sv << baseVar; - if (!className.empty()) { - _buf << ","sv << nll(classDecl) << indent(1) << "__name = "sv << className << (extend ? s(","sv) : Empty) << nll(classDecl); - } else { - _buf << nll(classDecl); - } - if (extend) { - _buf << indent(1) << "__parent = "sv << parentVar << nll(classDecl); - } - _buf << indent() << "}, {"sv << nll(classDecl); - if (extend) { - _buf << indent(1) << "__index = function(cls, name)"sv << nll(classDecl); - _buf << indent(2) << "local val = rawget("sv << baseVar << ", name)"sv << nll(classDecl); - _buf << indent(2) << "if val == nil then"sv << nll(classDecl); - _buf << indent(3) << "local parent = rawget(cls, \"__parent\")"sv << nll(classDecl); - _buf << indent(3) << "if parent then"sv << nll(classDecl); - _buf << indent(4) << "return parent[name]"sv << nll(classDecl); - _buf << indent(3) << "end"sv << nll(classDecl); - _buf << indent(2) << "else"sv << nll(classDecl); - _buf << indent(3) << "return val"sv << nll(classDecl); - _buf << indent(2) << "end"sv << nll(classDecl); - _buf << indent(1) << "end,"sv << nll(classDecl); - } else { - _buf << indent(1) << "__index = "sv << baseVar << ","sv << nll(classDecl); - } - _buf << indent(1) << "__call = function(cls, ...)"sv << nll(classDecl); - pushScope(); - auto selfVar = getUnusedName("_self_"sv); - addToScope(selfVar); - _buf << indent(1) << "local " << selfVar << " = setmetatable({}, "sv << baseVar << ")"sv << nll(classDecl); - _buf << indent(1) << "cls.__init("sv << selfVar << ", ...)"sv << nll(classDecl); - _buf << indent(1) << "return "sv << selfVar << nll(classDecl); - popScope(); - _buf << indent(1) << "end"sv << nll(classDecl); - _buf << indent() << "})"sv << nll(classDecl); - _buf << indent() << baseVar << ".__class = "sv << classVar << nll(classDecl); - if (!statements.empty()) _buf << indent() << "local self = "sv << classVar << nll(classDecl); - _buf << join(statements); - if (extend) { - _buf << indent() << "if "sv << parentVar << ".__inherited then"sv << nll(classDecl); - _buf << indent(1) << parentVar << ".__inherited("sv << parentVar << ", "sv << classVar << ")"sv << nll(classDecl); - _buf << indent() << "end"sv << nll(classDecl); - } - if (!assignItem.empty()) { - _buf << indent() << assignItem << " = "sv << classVar << nll(classDecl); - } - switch (usage) { - case ExpUsage::Return: { - _buf << indent() << "return "sv << classVar << nlr(classDecl); - break; - } - case ExpUsage::Assignment: { - _buf << tmp.back(); - break; - } - default: break; - } - temp.push_back(clearBuf()); - popScope(); - temp.push_back(indent() + s("end"sv) + nlr(classDecl)); - out.push_back(join(temp)); - } - - size_t transform_class_member_list(class_member_list_t* class_member_list, std::list& out, const std::string& classVar) { - str_list temp; - size_t count = 0; - for (auto keyValue : class_member_list->values.objects()) { - MemType type = MemType::Common; - BLOCK_START - auto normal_pair = ast_cast(keyValue); - BREAK_IF(!normal_pair); - auto keyName = normal_pair->key.as(); - BREAK_IF(!keyName); - std::string newSuperCall; - auto selfName = keyName->name.as(); - if (selfName) { - type = MemType::Property; - auto name = ast_cast(selfName->name); - if (!name) throw std::logic_error(debugInfo("Invalid class poperty name."sv, selfName->name)); - newSuperCall = classVar + s(".__parent."sv) + toString(name->name); - } else { - auto x = keyName; - auto nameNode = keyName->name.as(); - if (!nameNode) break; - auto name = toString(nameNode); - if (name == "new"sv) { - type = MemType::Builtin; - keyName->name.set(toAst("__init"sv, Name, x)); - newSuperCall = classVar + s(".__parent.__init"sv); - } else { - newSuperCall = classVar + s(".__parent.__base."sv) + name; - } - } - normal_pair->value->traverse([&](ast_node* node) { - if (node->getId() == "ClassDecl"_id) return traversal::Return; - if (auto chainValue = ast_cast(node)) { - if (auto callable = ast_cast(chainValue->items.front())) { - auto var = callable->item.get(); - if (toString(var) == "super"sv) { - auto insertSelfToArguments = [&](ast_node* item) { - auto x = item; - switch (item->getId()) { - case "InvokeArgs"_id: { - auto invoke = static_cast(item); - invoke->args.push_front(toAst("self"sv, Exp, x)); - return true; - } - case "Invoke"_id: { - auto invoke = static_cast(item); - invoke->args.push_front(toAst("self"sv, Exp, x)); - return true; - } - default: - return false; - } - }; - const auto& chainList = chainValue->items.objects(); - if (chainList.size() >= 2) { - auto it = chainList.begin(); - auto secondItem = *(++it); - if (!insertSelfToArguments(secondItem)) { - if (auto colonChainItem = ast_cast(secondItem)) { - if (chainList.size() > 2 && insertSelfToArguments(*(++it))) { - colonChainItem->switchToDot = true; - } - } - newSuperCall = classVar + s(".__parent"sv); - } - } else { - newSuperCall = classVar + s(".__parent"sv); - } - auto newChain = toAst(newSuperCall, ChainValue, chainValue); - chainValue->items.pop_front(); - const auto& items = newChain->items.objects(); - for (auto it = items.rbegin(); it != items.rend(); ++it) { - chainValue->items.push_front(*it); - } - } - } - } - return traversal::Continue; - }); - BLOCK_END - pushScope(); - if (type == MemType::Property) { - decIndentOffset(); - } - switch (keyValue->getId()) { - case "variable_pair"_id: - transform_variable_pair(static_cast(keyValue), temp); - break; - case "normal_pair"_id: - transform_normal_pair(static_cast(keyValue), temp); - break; - } - if (type == MemType::Property) { - incIndentOffset(); - } - popScope(); - out.push_back({temp.back(), type, keyValue}); - temp.clear(); - ++count; - } - return count; - } - - void transformAssignable(Assignable_t* assignable, str_list& out) { - auto item = assignable->item.get(); - switch (item->getId()) { - case "AssignableChain"_id: transformAssignableChain(static_cast(item), out); break; - case "Variable"_id: transformVariable(static_cast(item), out); break; - case "SelfName"_id: transformSelfName(static_cast(item), out, false); break; - default: break; - } - } - - void transformWithClosure(With_t* with, str_list& out) { - str_list temp; - temp.push_back(s("(function()"sv) + nll(with)); - pushScope(); - transformWith(with, temp, nullptr, true); - popScope(); - temp.push_back(indent() + s("end)()"sv)); - out.push_back(join(temp)); - } - - void transformWith(With_t* with, str_list& out, ExpList_t* assignList = nullptr, bool returnValue = false) { - auto x = with; - str_list temp; - std::string withVar; - bool scoped = false; - if (with->assigns) { - checkAssignable(with->valueList); - auto vars = getAssignVars(with); - if (vars.front().empty()) { - if (with->assigns->values.objects().size() == 1) { - auto var = singleVariableFrom(with->assigns->values.objects().front()); - if (!var.empty()) { - withVar = var; - } - } - if (withVar.empty()) { - withVar = getUnusedName("_with_"); - auto assignment = x->new_ptr(); - assignment->expList.set(toAst(withVar, ExpList, x)); - auto assign = x->new_ptr(); - assign->values.push_back(with->assigns->values.objects().front()); - assignment->action.set(assign); - if (!returnValue) { - scoped = true; - temp.push_back(indent() + s("do"sv) + nll(with)); - pushScope(); - } - transformAssignment(assignment, temp); - } - auto assignment = x->new_ptr(); - assignment->expList.set(with->valueList); - auto assign = x->new_ptr(); - assign->values.push_back(toAst(withVar, Exp, x)); - bool skipFirst = true; - for (auto value : with->assigns->values.objects()) { - if (skipFirst) { - skipFirst = false; - continue; - } - assign->values.push_back(value); - } - assignment->action.set(assign); - transformAssignment(assignment, temp); - } else { - withVar = vars.front(); - auto assignment = x->new_ptr(); - assignment->expList.set(with->valueList); - assignment->action.set(with->assigns); - if (!returnValue) { - scoped = true; - temp.push_back(indent() + s("do"sv) + nll(with)); - pushScope(); - } - transformAssignment(assignment, temp); - } - } else { - withVar = singleVariableFrom(with->valueList); - if (withVar.empty()) { - withVar = getUnusedName("_with_"); - auto assignment = x->new_ptr(); - assignment->expList.set(toAst(withVar, ExpList, x)); - auto assign = x->new_ptr(); - assign->values.dup(with->valueList->exprs); - assignment->action.set(assign); - if (!returnValue) { - scoped = true; - temp.push_back(indent() + s("do"sv) + nll(with)); - pushScope(); - } - transformAssignment(assignment, temp); - } - } - if (!scoped && !returnValue) { - pushScope(); - scoped = traversal::Stop == with->body->traverse([&](ast_node* node) { - if (auto statement = ast_cast(node)) { - ClassDecl_t* clsDecl = nullptr; - if (auto assignment = assignmentFrom(statement)) { - auto names = getAssignDefs(assignment->expList.get()); - if (!names.empty()) { - return traversal::Stop; - } - auto info = extractDestructureInfo(assignment); - if (!info.first.empty()) { - for (const auto& destruct : info.first) - for (const auto& item : destruct.items) - if (item.isVariable && !isDefined(item.name)) - return traversal::Stop; - } - BLOCK_START - auto assign = assignment->action.as(); - BREAK_IF(!assign); - BREAK_IF(assign->values.objects().size() != 1); - auto exp = ast_cast(assign->values.objects().front()); - BREAK_IF(!exp); - if (auto value = singleValueFrom(exp)) { - clsDecl = value->getByPath(); - } - BLOCK_END - } else if (auto expList = expListFrom(statement)) { - auto value = singleValueFrom(expList); - clsDecl = value->getByPath(); - } - if (clsDecl) { - auto variable = clsDecl->name.as(); - if (!isDefined(toString(variable))) return traversal::Stop; - } - return traversal::Return; - } - return traversal::Continue; - }); - popScope(); - if (scoped) { - temp.push_back(indent() + s("do"sv) + nll(with)); - pushScope(); - } - } - _withVars.push(withVar); - transformBody(with->body, temp); - _withVars.pop(); - if (assignList) { - auto assignment = x->new_ptr(); - assignment->expList.set(assignList); - auto assign = x->new_ptr(); - assign->values.push_back(toAst(withVar, Exp, x)); - assignment->action.set(assign); - transformAssignment(assignment, temp); - } - if (returnValue) { - auto stmt = lastStatementFrom(with->body); - if (!stmt->content.is()) { - temp.push_back(indent() + s("return "sv) + withVar + nll(with)); - } - } - if (scoped) { - popScope(); - temp.push_back(indent() + s("end"sv) + nll(with)); - } - out.push_back(join(temp)); - } - - void transform_const_value(const_value_t* const_value, str_list& out) { - out.push_back(toString(const_value)); - } - - void transformExport(Export_t* exportNode, str_list& out) { - auto x = exportNode; - auto item = exportNode->item.get(); - switch (item->getId()) { - case "ClassDecl"_id: { - auto classDecl = static_cast(item); - if (classDecl->name && classDecl->name->item->getId() == "Variable"_id) { - markVarExported(ExportMode::Any, true); - addExportedVar(toString(classDecl->name->item)); - } - transformClassDecl(classDecl, out); - break; - } - case "export_op"_id: - if (toString(item) == "*"sv) { - markVarExported(ExportMode::Any, false); - } else { - markVarExported(ExportMode::Capital, false); - } - break; - case "export_values"_id: { - markVarExported(ExportMode::Any, true); - auto values = exportNode->item.to(); - if (values->valueList) { - auto expList = x->new_ptr(); - for (auto name : values->nameList->names.objects()) { - addExportedVar(toString(name)); - auto callable = x->new_ptr(); - callable->item.set(name); - auto chainValue = x->new_ptr(); - chainValue->items.push_back(callable); - auto value = x->new_ptr(); - value->item.set(chainValue); - auto exp = x->new_ptr(); - exp->value.set(value); - expList->exprs.push_back(exp); - } - auto assignment = x->new_ptr(); - assignment->expList.set(expList); - auto assign = x->new_ptr(); - assign->values.dup(values->valueList->exprs); - assignment->action.set(assign); - transformAssignment(assignment, out); - } else { - for (auto name : values->nameList->names.objects()) { - addExportedVar(toString(name)); - } - } - break; - } - default: - break; - } - } - - void transformTable(ast_node* table, const node_container& pairs, str_list& out) { - if (pairs.empty()) { - out.push_back(s("{ }"sv)); - return; - } - str_list temp; - pushScope(); - for (auto pair : pairs) { - switch (pair->getId()) { - case "Exp"_id: transformExp(static_cast(pair), temp); break; - case "variable_pair"_id: transform_variable_pair(static_cast(pair), temp); break; - case "normal_pair"_id: transform_normal_pair(static_cast(pair), temp); break; - } - temp.back() = indent() + temp.back() + (pair == pairs.back() ? Empty : s(","sv)) + nll(pair); - } - out.push_back(s("{"sv) + nll(table) + join(temp)); - popScope(); - out.back() += (indent() + s("}"sv)); - } - - void transform_simple_table(simple_table_t* table, str_list& out) { - transformTable(table, table->pairs.objects(), out); - } - - void transformTblComprehension(TblComprehension_t* comp, str_list& out) { - str_list kv; - std::string tbl = getUnusedName("_tbl_"); - addToScope(tbl); - str_list temp; - auto compInner = comp->forLoop.get(); - for (auto item : compInner->items.objects()) { - switch (item->getId()) { - case "CompForEach"_id: - transformCompForEach(static_cast(item), temp); - break; - case "CompFor"_id: - transformCompFor(static_cast(item), temp); - break; - case "Exp"_id: - transformExp(static_cast(item), temp); - temp.back() = indent() + s("if "sv) + temp.back() + s(" then"sv) + nll(item); - pushScope(); - break; - } - } - transformExp(comp->key, kv); - if (comp->value) { - transformExp(comp->value->value, kv); - } - for (size_t i = 0; i < compInner->items.objects().size(); ++i) { - popScope(); - } - _buf << indent() << "local "sv << tbl << " = { }"sv << nll(comp); - _buf << join(temp); - pushScope(); - if (!comp->value) { - auto keyVar = getUnusedName("_key_"); - auto valVar = getUnusedName("_val_"); - _buf << indent(int(temp.size()) - 1) << "local "sv << keyVar << ", "sv << valVar << " = "sv << kv.front() << nll(comp); - kv.front() = keyVar; - kv.push_back(valVar); - } - _buf << indent(int(temp.size()) - 1) << tbl << "["sv << kv.front() << "] = "sv << kv.back() << nll(comp); - for (int ind = int(temp.size()) - 2; ind > -1 ; --ind) { - _buf << indent(ind) << "end"sv << nll(comp); - } - popScope(); - _buf << indent() << "end"sv << nll(comp); - out.push_back(tbl); - out.push_back(clearBuf()); - } - - void transformTblCompInPlace(TblComprehension_t* comp, ExpList_t* expList, str_list& out) { - auto x = comp; - str_list temp; - auto ind = indent(); - pushScope(); - transformTblComprehension(comp, temp); - auto assign = x->new_ptr(); - assign->values.push_back(toAst(temp.front(), Exp, x)); - auto assignment = x->new_ptr(); - assignment->expList.set(expList); - assignment->action.set(assign); - transformAssignment(assignment, temp); - out.push_back( - ind + s("do"sv) + nll(comp) + - *(++temp.begin()) + - temp.back()); - popScope(); - out.back() = out.back() + indent() + s("end"sv) + nlr(comp); - } - - void transformTblCompReturn(TblComprehension_t* comp, str_list& out) { - str_list temp; - transformTblComprehension(comp, temp); - out.push_back(temp.back() + indent() + s("return "sv) + temp.front() + nlr(comp)); - } - - void transformTblCompClosure(TblComprehension_t* comp, str_list& out) { - str_list temp; - std::string before = s("(function()"sv) + nll(comp); - pushScope(); - transformTblComprehension(comp, temp); - const auto& tbVar = temp.front(); - const auto& compBody = temp.back(); - out.push_back( - before + - compBody + - indent() + s("return "sv) + tbVar + nlr(comp)); - popScope(); - out.back() = out.back() + indent() + s("end)()"sv); - } - - void transformCompFor(CompFor_t* comp, str_list& out) { - str_list temp; - std::string varName = toString(comp->varName); - transformExp(comp->startValue, temp); - transformExp(comp->stopValue, temp); - if (comp->stepValue) { - transformExp(comp->stepValue->value, temp); - } else { - temp.emplace_back(); - } - auto it = temp.begin(); - const auto& start = *it; - const auto& stop = *(++it); - const auto& step = *(++it); - _buf << indent() << "for "sv << varName << " = "sv << start << ", "sv << stop << (step.empty() ? Empty : s(", "sv) + step) << " do"sv << nll(comp); - out.push_back(clearBuf()); - pushScope(); - addToScope(varName); - } - - void transformTableBlock(TableBlock_t* table, str_list& out) { - transformTable(table, table->values.objects(), out); - } - - void transformDo(Do_t* doNode, str_list& out, bool implicitReturn = false) { - str_list temp; - temp.push_back(indent() + s("do"sv) + nll(doNode)); - pushScope(); - transformBody(doNode->body, temp, implicitReturn); - popScope(); - temp.push_back(indent() + s("end"sv) + nlr(doNode)); - out.push_back(join(temp)); - } - - void transformDoClosure(Do_t* doNode, str_list& out) { - str_list temp; - temp.push_back(s("(function()"sv) + nll(doNode)); - pushScope(); - transformBody(doNode->body, temp, true); - popScope(); - temp.push_back(indent() + s("end)()"sv)); - out.push_back(join(temp)); - } - - void transformImport(Import_t* import, str_list& out) { - str_list temp; - auto x = import; - auto objVar = singleVariableFrom(import->exp); - ast_ptr objAssign; - if (objVar.empty()) { - objVar = getUnusedName("_obj_"sv); - auto expList = toAst(objVar, ExpList, x); - auto assign = x->new_ptr(); - assign->values.push_back(import->exp); - auto assignment = x->new_ptr(); - assignment->expList.set(expList); - assignment->action.set(assign); - objAssign.set(assignment); - } - auto expList = x->new_ptr(); - auto assign = x->new_ptr(); - for (auto name : import->names.objects()) { - switch (name->getId()) { - case "Variable"_id: { - auto var = ast_to(name); - { - auto callable = toAst(objVar, Callable, x); - auto dotChainItem = x->new_ptr(); - dotChainItem->name.set(var->name); - auto chainValue = x->new_ptr(); - chainValue->items.push_back(callable); - chainValue->items.push_back(dotChainItem); - auto value = x->new_ptr(); - value->item.set(chainValue); - auto exp = x->new_ptr(); - exp->value.set(value); - assign->values.push_back(exp); - } - auto callable = x->new_ptr(); - callable->item.set(var); - auto chainValue = x->new_ptr(); - chainValue->items.push_back(callable); - auto value = x->new_ptr(); - value->item.set(chainValue); - auto exp = x->new_ptr(); - exp->value.set(value); - expList->exprs.push_back(exp); - break; - } - case "colon_import_name"_id: { - auto var = static_cast(name)->name.get(); - { - auto nameNode = var->name.get(); - auto callable = toAst(objVar, Callable, x); - auto colonChain = x->new_ptr(); - colonChain->name.set(nameNode); - auto chainValue = x->new_ptr(); - chainValue->items.push_back(callable); - chainValue->items.push_back(colonChain); - auto value = x->new_ptr(); - value->item.set(chainValue); - auto exp = x->new_ptr(); - exp->value.set(value); - assign->values.push_back(exp); - } - auto callable = x->new_ptr(); - callable->item.set(var); - auto chainValue = x->new_ptr(); - chainValue->items.push_back(callable); - auto value = x->new_ptr(); - value->item.set(chainValue); - auto exp = x->new_ptr(); - exp->value.set(value); - expList->exprs.push_back(exp); - break; - } - } - } - if (objAssign) { - auto preDef = getPredefine(transformAssignDefs(expList)); - if (!preDef.empty()) { - temp.push_back(preDef + nll(import)); - } - temp.push_back(indent() + s("do"sv) + nll(import)); - pushScope(); - transformAssignment(objAssign, temp); - } - auto assignment = x->new_ptr(); - assignment->expList.set(expList); - assignment->action.set(assign); - transformAssignment(assignment, temp); - if (objAssign) { - popScope(); - temp.push_back(indent() + s("end"sv) + nlr(import)); - } - out.push_back(join(temp)); - } - - void transformWhileInPlace(While_t* whileNode, str_list& out, ExpList_t* expList = nullptr) { - auto x = whileNode; - str_list temp; - if (expList) { - temp.push_back(indent() + s("do"sv) + nll(whileNode)); - } - pushScope(); - auto accumVar = getUnusedName("_accum_"sv); - addToScope(accumVar); - auto lenVar = getUnusedName("_len_"sv); - addToScope(lenVar); - temp.push_back(indent() + s("local "sv) + accumVar + s(" = { }"sv) + nll(whileNode)); - temp.push_back(indent() + s("local "sv) + lenVar + s(" = 1"sv) + nll(whileNode)); - transformExp(whileNode->condition, temp); - temp.back() = indent() + s("while "sv) + temp.back() + s(" do"sv) + nll(whileNode); - pushScope(); - auto assignLeft = toAst(accumVar + s("["sv) + lenVar + s("]"sv), ExpList, x); - assignLastExplist(assignLeft, whileNode->body); - auto lenLine = lenVar + s(" = "sv) + lenVar + s(" + 1"sv) + nlr(whileNode); - transformLoopBody(whileNode->body, temp, lenLine); - popScope(); - temp.push_back(indent() + s("end"sv) + nlr(whileNode)); - if (expList) { - auto assign = x->new_ptr(); - assign->values.push_back(toAst(accumVar, Exp, x)); - auto assignment = x->new_ptr(); - assignment->expList.set(expList); - assignment->action.set(assign); - transformAssignment(assignment, temp); - } else { - temp.push_back(indent() + s("return "sv) + accumVar + nlr(whileNode)); - } - popScope(); - if (expList) { - temp.push_back(indent() + s("end"sv) + nlr(whileNode)); - } - out.push_back(join(temp)); - } - - void transformWhileClosure(While_t* whileNode, str_list& out) { - auto x = whileNode; - str_list temp; - temp.push_back(s("(function() "sv) + nll(whileNode)); - pushScope(); - auto accumVar = getUnusedName("_accum_"sv); - addToScope(accumVar); - auto lenVar = getUnusedName("_len_"sv); - addToScope(lenVar); - temp.push_back(indent() + s("local "sv) + accumVar + s(" = { }"sv) + nll(whileNode)); - temp.push_back(indent() + s("local "sv) + lenVar + s(" = 1"sv) + nll(whileNode)); - transformExp(whileNode->condition, temp); - temp.back() = indent() + s("while "sv) + temp.back() + s(" do"sv) + nll(whileNode); - pushScope(); - auto assignLeft = toAst(accumVar + s("["sv) + lenVar + s("]"sv), ExpList, x); - assignLastExplist(assignLeft, whileNode->body); - auto lenLine = lenVar + s(" = "sv) + lenVar + s(" + 1"sv) + nlr(whileNode); - transformLoopBody(whileNode->body, temp, lenLine); - popScope(); - temp.push_back(indent() + s("end"sv) + nlr(whileNode)); - temp.push_back(indent() + s("return "sv) + accumVar + nlr(whileNode)); - popScope(); - temp.push_back(indent() + s("end)()"sv)); - out.push_back(join(temp)); - } - - void transformWhile(While_t* whileNode, str_list& out) { - str_list temp; - pushScope(); - transformExp(whileNode->condition, temp); - transformLoopBody(whileNode->body, temp, Empty); - popScope(); - _buf << indent() << "while "sv << temp.front() << " do"sv << nll(whileNode); - _buf << temp.back(); - _buf << indent() << "end"sv << nlr(whileNode); - out.push_back(clearBuf()); - } - - void transformSwitchClosure(Switch_t* switchNode, str_list& out) { - str_list temp; - temp.push_back(s("(function()"sv) + nll(switchNode)); - pushScope(); - transformSwitch(switchNode, temp, true); - popScope(); - temp.push_back(indent() + s("end)()"sv)); - out.push_back(join(temp)); - } - - void transformSwitch(Switch_t* switchNode, str_list& out, bool implicitReturn = false) { - str_list temp; - auto objVar = singleVariableFrom(switchNode->target); - if (objVar.empty()) { - objVar = getUnusedName("_exp_"sv); - addToScope(objVar); - transformExp(switchNode->target, temp); - _buf << indent() << "local "sv << objVar << " = "sv << temp.back() << nll(switchNode); - temp.back() = clearBuf(); - } - const auto& branches = switchNode->branches.objects(); - for (auto branch_ : branches) { - auto branch = static_cast(branch_); - temp.push_back(indent() + s(branches.front() == branch ? "if"sv : "elseif"sv)); - str_list tmp; - const auto& exprs = branch->valueList->exprs.objects(); - for (auto exp_ : exprs) { - auto exp = static_cast(exp_); - transformExp(exp, tmp); - if (!singleValueFrom(exp)) { - tmp.back() = s("("sv) + tmp.back() + s(")"sv); - } - temp.back().append(s(" "sv) + tmp.back() + s(" == "sv) + objVar + - s(exp == exprs.back() ? ""sv : " or"sv)); - } - temp.back().append(s(" then"sv) + nll(branch)); - pushScope(); - transformBody(branch->body, temp, implicitReturn); - popScope(); - } - if (switchNode->lastBranch) { - temp.push_back(indent() + s("else"sv) + nll(switchNode->lastBranch)); - pushScope(); - transformBody(switchNode->lastBranch, temp, implicitReturn); - popScope(); - } - temp.push_back(indent() + s("end"sv) + nlr(switchNode)); - out.push_back(join(temp)); - } - - void transformLocal(Local_t* local, str_list& out) { - if (!local->forceDecls.empty() || !local->decls.empty()) { - str_list defs; - for (const auto& decl : local->forceDecls) { - forceAddToScope(decl); - defs.push_back(decl); - } - for (const auto& decl : local->decls) { - if (addToScope(decl)) { - defs.push_back(decl); - } - } - auto preDefine = getPredefine(defs); - if (!preDefine.empty()) { - out.push_back(preDefine + nll(local)); - } - } - } - - void transformBreakLoop(BreakLoop_t* breakLoop, str_list& out) { - auto keyword = toString(breakLoop); - if (keyword == "break"sv) { - out.push_back(indent() + keyword + nll(breakLoop)); - return; - } - if (_continueVars.empty()) throw std::logic_error(debugInfo("Continue is not inside a loop."sv, breakLoop)); - _buf << indent() << _continueVars.top() << " = true"sv << nll(breakLoop); - _buf << indent() << "break"sv << nll(breakLoop); - out.push_back(clearBuf()); - } -}; - -const std::string MoonCompliler::Empty; - -std::pair moonCompile(const std::string& codes, bool implicitReturnRoot, bool lineNumber) { - return MoonCompliler{}.complile(codes, false, implicitReturnRoot, lineNumber); -} - -std::pair moonCompile(const std::string& codes, std::list& globals, bool implicitReturnRoot, bool lineNumber) { - auto compiler = MoonCompliler{}; - auto result = compiler.complile(codes, true, implicitReturnRoot, lineNumber); - for (const auto& var : compiler.getGlobals()) { - int line,col; - std::tie(line,col) = var.second; - globals.push_back({var.first, line, col}); - } - return result; -} - -} // namespace MoonP diff --git a/MoonParser/moon_compiler.h b/MoonParser/moon_compiler.h deleted file mode 100644 index e54c774..0000000 --- a/MoonParser/moon_compiler.h +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once - -#include -#include -#include - -namespace MoonP { - -std::pair moonCompile(const std::string& codes, bool implicitReturnRoot = true, bool lineNumber = true); - -struct GlobalVar { - std::string name; - int line; - int col; -}; -std::pair moonCompile(const std::string& codes, std::list& globals, bool implicitReturnRoot = true, bool lineNumber = true); - -} // namespace MoonP diff --git a/MoonParser/moon_parser.cpp b/MoonParser/moon_parser.cpp deleted file mode 100644 index 2b93c22..0000000 --- a/MoonParser/moon_parser.cpp +++ /dev/null @@ -1,513 +0,0 @@ -#include "moon_parser.h" - -namespace MoonP { - -std::unordered_set State::luaKeywords = { - "and", "break", "do", "else", "elseif", - "end", "false", "for", "function", "if", - "in", "local", "nil", "not", "or", - "repeat", "return", "then", "true", "until", - "while" -}; - -std::unordered_set State::keywords = { - "and", "break", "do", "else", "elseif", - "end", "false", "for", "function", "if", - "in", "local", "nil", "not", "or", - "repeat", "return", "then", "true", "until", - "while", // Lua keywords - "class", "continue", "export", "extends", "from", - "import", "switch", "unless", "using", "when", - "with" // Moon keywords -}; - -rule plain_space = *set(" \t"); -rule Break = nl(-expr('\r') >> '\n'); -rule Any = Break | any(); -rule White = *(set(" \t") | Break); -rule Stop = Break | eof(); -rule Comment = "--" >> *(not_(set("\r\n")) >> Any) >> and_(Stop); -rule Indent = *set(" \t"); -rule Space = plain_space >> -Comment; -rule SomeSpace = +set(" \t") >> -Comment; -rule SpaceBreak = Space >> Break; -rule EmptyLine = SpaceBreak; -rule AlphaNum = range('a', 'z') | range('A', 'Z') | range('0', '9') | '_'; -rule Name = (range('a', 'z') | range('A', 'Z') | '_') >> *AlphaNum; -rule Num = - ( - "0x" >> - +(range('0', '9') | range('a', 'f') | range('A', 'F')) - ) | ( - ( - (+range('0', '9') >> -('.' >> +range('0', '9'))) | - ('.' >> +range('0', '9')) - ) >> -(set("eE") >> -expr('-') >> +range('0', '9')) - ); -rule Cut = false_(); -rule Seperator = true_(); - -#define sym(str) (Space >> str) -#define symx(str) expr(str) -#define ensure(patt, finally) (((patt) >> (finally)) | ((finally) >> (Cut))) -#define key(str) (Space >> str >> not_(AlphaNum)) - -rule Variable = user(Name, [](const item_t& item) { - State* st = reinterpret_cast(item.user_data); - for (auto it = item.begin; it != item.end; ++it) st->buffer += static_cast(*it); - auto it = State::keywords.find(st->buffer); - st->buffer.clear(); - return it == State::keywords.end(); -}); - -rule LuaKeyword = user(Name, [](const item_t& item) { - State* st = reinterpret_cast(item.user_data); - for (auto it = item.begin; it != item.end; ++it) st->buffer += static_cast(*it); - auto it = State::luaKeywords.find(st->buffer); - st->buffer.clear(); - return it != State::luaKeywords.end(); -}); - -rule self = expr('@'); -rule self_name = '@' >> Name; -rule self_class = expr("@@"); -rule self_class_name = "@@" >> Name; - -rule SelfName = Space >> (self_class_name | self_class | self_name | self); -rule KeyName = SelfName | Space >> Name; -rule VarArg = Space >> "..."; - -rule check_indent = user(Indent, [](const item_t& item) { - int indent = 0; - for (input_it i = item.begin; i != item.end; ++i) { - switch (*i) { - case ' ': indent++; break; - case '\t': indent += 4; break; - } - } - State* st = reinterpret_cast(item.user_data); - return st->indents.top() == indent; -}); -rule CheckIndent = and_(check_indent); - -rule advance = user(Indent, [](const item_t& item) { - int indent = 0; - for (input_it i = item.begin; i != item.end; ++i) { - switch (*i) { - case ' ': indent++; break; - case '\t': indent += 4; break; - } - } - State* st = reinterpret_cast(item.user_data); - int top = st->indents.top(); - if (top != -1 && indent > top) { - st->indents.push(indent); - return true; - } - return false; -}); -rule Advance = and_(advance); - -rule push_indent = user(Indent, [](const item_t& item) { - int indent = 0; - for (input_it i = item.begin; i != item.end; ++i) { - switch (*i) { - case ' ': indent++; break; - case '\t': indent += 4; break; - } - } - State* st = reinterpret_cast(item.user_data); - st->indents.push(indent); - return true; -}); -rule PushIndent = and_(push_indent); - -rule PreventIndent = user(true_(), [](const item_t& item) { - State* st = reinterpret_cast(item.user_data); - st->indents.push(-1); - return true; -}); - -rule PopIndent = user(true_(), [](const item_t& item) { - State* st = reinterpret_cast(item.user_data); - st->indents.pop(); - return true; -}); - -extern rule Block; - -rule InBlock = Advance >> Block >> PopIndent; - -extern rule NameList; - -rule local_flag = expr('*') | expr('^'); -rule Local = key("local") >> ((Space >> local_flag) | NameList); - -rule colon_import_name = sym('\\') >> Space >> Variable; -rule ImportName = colon_import_name | Space >> Variable; -rule ImportNameList = Seperator >> *SpaceBreak >> ImportName >> *((+SpaceBreak | sym(',') >> *SpaceBreak) >> ImportName); - -extern rule Exp; - -rule Import = key("import") >> ImportNameList >> *SpaceBreak >> key("from") >> Exp; -rule BreakLoop = (expr("break") | expr("continue")) >> not_(AlphaNum); - -extern rule ExpListLow, ExpList, Assign; - -rule Return = key("return") >> -ExpListLow; -rule WithExp = ExpList >> -Assign; - -extern rule DisableDo, PopDo, Body; - -rule With = key("with") >> DisableDo >> ensure(WithExp, PopDo) >> -key("do") >> Body; -rule SwitchCase = key("when") >> ExpList >> -key("then") >> Body; -rule SwitchElse = key("else") >> Body; - -rule SwitchBlock = *EmptyLine >> - Advance >> Seperator >> - SwitchCase >> - *(+Break >> SwitchCase) >> - -(+Break >> SwitchElse) >> - PopIndent; - -rule Switch = key("switch") >> - DisableDo >> ensure(Exp, PopDo) >> - -key("do") >> -Space >> Break >> SwitchBlock; - -rule IfCond = Exp >> -Assign; -rule IfElseIf = -(Break >> *EmptyLine >> CheckIndent) >> key("elseif") >> IfCond >> -key("then") >> Body; -rule IfElse = -(Break >> *EmptyLine >> CheckIndent) >> key("else") >> Body; -rule If = key("if") >> Seperator >> IfCond >> -key("then") >> Body >> *IfElseIf >> -IfElse; -rule Unless = key("unless") >> Seperator >> IfCond >> -key("then") >> Body >> *IfElseIf >> -IfElse; - -rule While = key("while") >> DisableDo >> ensure(Exp, PopDo) >> -key("do") >> Body; - -rule for_step_value = sym(',') >> Exp; -rule for_args = Space >> Variable >> sym('=') >> Exp >> sym(',') >> Exp >> -for_step_value; - -rule For = key("for") >> DisableDo >> - ensure(for_args, PopDo) >> - -key("do") >> Body; - -extern rule AssignableNameList; - -extern rule star_exp; - -rule for_in = star_exp | ExpList; - -rule ForEach = key("for") >> AssignableNameList >> key("in") >> - DisableDo >> ensure(for_in, PopDo) >> - -key("do") >> Body; - -rule Do = user(key("do") >> Body, [](const item_t& item) -{ - State* st = reinterpret_cast(item.user_data); - return st->doStack.empty() || st->doStack.top(); -}); - -rule DisableDo = user(true_(), [](const item_t& item) -{ - State* st = reinterpret_cast(item.user_data); - st->doStack.push(false); - return true; -}); - -rule PopDo = user(true_(), [](const item_t& item) -{ - State* st = reinterpret_cast(item.user_data); - st->doStack.pop(); - return true; -}); - -extern rule CompInner; - -rule Comprehension = sym('[') >> Exp >> CompInner >> sym(']'); -rule comp_value = sym(',') >> Exp; -rule TblComprehension = sym('{') >> (Exp >> -comp_value) >> CompInner >> sym('}'); - -extern rule CompForEach, CompFor, CompClause; - -rule CompInner = Seperator >> (CompForEach | CompFor) >> *CompClause; -rule star_exp = sym('*') >> Exp; -rule CompForEach = key("for") >> AssignableNameList >> key("in") >> (star_exp | Exp); -rule CompFor = key("for") >> Space >> Variable >> sym('=') >> Exp >> sym(',') >> Exp >> -for_step_value; -rule CompClause = CompFor | CompForEach | key("when") >> Exp; - -extern rule TableBlock; - -rule Assign = sym('=') >> Seperator >> (With | If | Switch | TableBlock | Exp >> *((sym(',') | sym(';')) >> Exp)); - -rule update_op = - expr("..") | - expr("+") | - expr("-") | - expr("*") | - expr("/") | - expr("%") | - expr("or") | - expr("and") | - expr("&") | - expr("|") | - expr(">>") | - expr("<<"); - -rule Update = Space >> update_op >> expr("=") >> Exp; - -rule BinaryOperator = - (expr("or") >> not_(AlphaNum)) | - (expr("and") >> not_(AlphaNum)) | - expr("<=") | - expr(">=") | - expr("~=") | - expr("!=") | - expr("==") | - expr("..") | - expr("<<") | - expr(">>") | - expr("//") | - set("+-*/%^><|&"); - -extern rule AssignableChain; - -rule Assignable = AssignableChain | Space >> Variable | SelfName; - -extern rule Value; - -rule exp_op_value = Space >> BinaryOperator >> *SpaceBreak >> Value; -rule Exp = Value >> *exp_op_value; - -extern rule Chain, Callable, InvokeArgs; - -rule ChainValue = Seperator >> (Chain | Callable) >> -InvokeArgs; - -extern rule KeyValue, String, SimpleValue; - -rule simple_table = Seperator >> KeyValue >> *(sym(',') >> KeyValue); -rule Value = SimpleValue | simple_table | ChainValue | String; - -extern rule LuaString; - -rule single_string_inner = expr("\\'") | "\\\\" | not_(expr('\'')) >> Any; -rule SingleString = symx('\'') >> *single_string_inner >> sym('\''); -rule interp = symx("#{") >> Exp >> sym('}'); -rule double_string_plain = expr("\\\"") | "\\\\" | not_(expr('"')) >> Any; -rule double_string_inner = +(not_(interp) >> double_string_plain); -rule double_string_content = double_string_inner | interp; -rule DoubleString = symx('"') >> Seperator >> *double_string_content >> sym('"'); -rule String = Space >> (DoubleString | SingleString | LuaString); - -rule lua_string_open = '[' >> *expr('=') >> '['; -rule lua_string_close = ']' >> *expr('=') >> ']'; - -rule LuaStringOpen = user(lua_string_open, [](const item_t& item) -{ - size_t count = std::distance(item.begin, item.end); - State* st = reinterpret_cast(item.user_data); - st->stringOpen = count; - return true; -}); - -rule LuaStringClose = user(lua_string_close, [](const item_t& item) -{ - size_t count = std::distance(item.begin, item.end); - State* st = reinterpret_cast(item.user_data); - return st->stringOpen == count; -}); - -rule LuaStringContent = *(not_(LuaStringClose) >> (Break | Any)); - -rule LuaString = user(LuaStringOpen >> -Break >> LuaStringContent >> LuaStringClose, [](const item_t& item) -{ - State* st = reinterpret_cast(item.user_data); - st->stringOpen = -1; - return true; -}); - -rule Parens = sym('(') >> *SpaceBreak >> Exp >> *SpaceBreak >> sym(')'); -rule Callable = Space >> Variable | SelfName | VarArg | Parens; -rule FnArgsExpList = Exp >> *((Break | sym(',')) >> White >> Exp); - -rule FnArgs = (symx('(') >> *SpaceBreak >> -FnArgsExpList >> *SpaceBreak >> sym(')')) | - (sym('!') >> not_(expr('='))); - -extern rule ChainItems, DotChainItem, ColonChain; - -rule chain_call = (Callable | String) >> ChainItems; -rule chain_item = and_(set(".\\")) >> ChainItems; -rule chain_dot_chain = DotChainItem >> -ChainItems; - -rule Chain = chain_call | chain_item | - Space >> (chain_dot_chain | ColonChain); - -rule AssignableChain = Seperator >> Chain; - -extern rule ChainItem; - -rule chain_with_colon = +ChainItem >> -ColonChain; -rule ChainItems = chain_with_colon | ColonChain; - -extern rule Invoke, Slice; - -rule Index = symx('[') >> Exp >> sym(']'); -rule ChainItem = Invoke | DotChainItem | Slice | Index; -rule DotChainItem = symx('.') >> Name; -rule ColonChainItem = symx('\\') >> (LuaKeyword | Name); -rule invoke_chain = Invoke >> -ChainItems; -rule ColonChain = ColonChainItem >> -invoke_chain; - -rule default_value = true_(); -rule Slice = - symx('[') >> - (Exp | default_value) >> - sym(',') >> - (Exp | default_value) >> - (sym(',') >> Exp | default_value) >> - sym(']'); - -rule Invoke = Seperator >> ( - FnArgs | - SingleString | - DoubleString | - and_(expr('[')) >> LuaString); - -extern rule TableValueList, TableLitLine; - -rule TableValue = KeyValue | Exp; - -rule table_lit_lines = SpaceBreak >> TableLitLine >> *(-sym(',') >> SpaceBreak >> TableLitLine) >> -sym(','); - -rule TableLit = - sym('{') >> Seperator >> - -TableValueList >> - -sym(',') >> - -table_lit_lines >> - White >> sym('}'); - -rule TableValueList = TableValue >> *(sym(',') >> TableValue); - -rule TableLitLine = -( - PushIndent >> (TableValueList >> PopIndent | PopIndent) -) | ( - Space -); - -extern rule KeyValueLine; - -rule TableBlockInner = Seperator >> KeyValueLine >> *(+(SpaceBreak) >> KeyValueLine); -rule TableBlock = +(SpaceBreak) >> Advance >> ensure(TableBlockInner, PopIndent); - -extern rule Statement; - -rule class_member_list = Seperator >> KeyValue >> *(sym(',') >> KeyValue); -rule ClassLine = CheckIndent >> (class_member_list | Statement) >> -sym(','); -rule ClassBlock = +(SpaceBreak) >> Advance >>Seperator >> ClassLine >> *(+(SpaceBreak) >> ClassLine) >> PopIndent; - -rule ClassDecl = - key("class") >> not_(expr(':')) >> - -Assignable >> - -(key("extends") >> PreventIndent >> ensure(Exp, PopIndent)) >> - -ClassBlock; - -rule export_values = NameList >> -(sym('=') >> ExpListLow); -rule export_op = expr('*') | expr('^'); -rule Export = key("export") >> (ClassDecl | (Space >> export_op) | export_values); - -rule variable_pair = sym(':') >> not_(SomeSpace) >> Space >> Variable; - -rule normal_pair = -( - KeyName | - sym('[') >> Exp >> sym(']') | - Space >> DoubleString | - Space >> SingleString -) >> -symx(':') >> -(Exp | TableBlock | +(SpaceBreak) >> Exp); - -rule KeyValue = variable_pair | normal_pair; - -rule KeyValueList = KeyValue >> *(sym(',') >> KeyValue); -rule KeyValueLine = CheckIndent >> KeyValueList >> -sym(','); - -rule FnArgDef = (Space >> Variable | SelfName) >> -(sym('=') >> Exp); - -rule FnArgDefList = Seperator >> -( - ( - FnArgDef >> - *((sym(',') | Break) >> White >> FnArgDef) >> - -((sym(',') | Break) >> White >> VarArg) - ) | ( - VarArg - ) -); - -rule outer_var_shadow = key("using") >> (NameList | Space >> expr("nil")); - -rule FnArgsDef = sym('(') >> White >> -FnArgDefList >> -outer_var_shadow >> White >> sym(')'); -rule fn_arrow = expr("->") | expr("=>"); -rule FunLit = -FnArgsDef >> Space >> fn_arrow >> -Body; - -rule NameList = Seperator >> Space >> Variable >> *(sym(',') >> Space >> Variable); -rule NameOrDestructure = Space >> Variable | TableLit; -rule AssignableNameList = Seperator >> NameOrDestructure >> *(sym(',') >> NameOrDestructure); - -rule ExpList = Seperator >> Exp >> *(sym(',') >> Exp); -rule ExpListLow = Seperator >> Exp >> *((sym(',') | sym(';')) >> Exp); - -rule ArgLine = CheckIndent >> Exp >> *(sym(',') >> Exp); -rule ArgBlock = ArgLine >> *(sym(',') >> SpaceBreak >> ArgLine) >> PopIndent; - -rule invoke_args_with_table = - sym(',') >> - ( - TableBlock | - SpaceBreak >> Advance >> ArgBlock >> -TableBlock - ); - -rule InvokeArgs = - not_(expr('-')) >> Seperator >> - ( - Exp >> *(sym(',') >> Exp) >> -(invoke_args_with_table | TableBlock) | - TableBlock - ); - -rule const_value = (expr("nil") | expr("true") | expr("false")) >> not_(AlphaNum); -rule minus_exp = expr('-') >> not_(SomeSpace) >> Exp; -rule sharp_exp = expr('#') >> Exp; -rule tilde_exp = expr('~') >> Exp; -rule not_exp = expr("not") >> not_(AlphaNum) >> Exp; -rule unary_exp = minus_exp | sharp_exp | tilde_exp | not_exp; - -rule SimpleValue = - (Space >> const_value) | - If | Unless | Switch | With | ClassDecl | ForEach | For | While | Do | - (Space >> unary_exp) | - TblComprehension | TableLit | Comprehension | FunLit | - (Space >> Num); - -rule ExpListAssign = ExpList >> -(Update | Assign); - -rule if_else_line = key("if") >> Exp >> (key("else") >> Exp | default_value); -rule unless_line = key("unless") >> Exp; - -rule statement_appendix = (if_else_line | unless_line | CompInner) >> Space; -rule Statement = -( - Import | While | For | ForEach | - Return | Local | Export | Space >> BreakLoop | - ExpListAssign -) >> Space >> --statement_appendix; - -rule Body = -Space >> Break >> *EmptyLine >> InBlock | Statement; - -rule empty_line_stop = Space >> and_(Stop); -rule Line = CheckIndent >> Statement | empty_line_stop; -rule Block = Seperator >> Line >> *(+Break >> Line); - -rule Shebang = expr("#!") >> *(not_(Stop) >> Any); -rule File = White >> -Shebang >> Block >> eof(); - -} // namespace MoonP diff --git a/MoonParser/moon_parser.h b/MoonParser/moon_parser.h deleted file mode 100644 index 07380cc..0000000 --- a/MoonParser/moon_parser.h +++ /dev/null @@ -1,27 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include -#include "ast.hpp" -using namespace parserlib; - -namespace MoonP { - -struct State { - State() { - indents.push(0); - stringOpen = -1; - } - std::string buffer; - size_t stringOpen; - std::stack indents; - std::stack doStack; - static std::unordered_set luaKeywords; - static std::unordered_set keywords; -}; - -} // namespace MoonP diff --git a/MoonParser/moonc.cpp b/MoonParser/moonc.cpp deleted file mode 100644 index 1a383fe..0000000 --- a/MoonParser/moonc.cpp +++ /dev/null @@ -1,21 +0,0 @@ -#include -#include "moon_compiler.h" - -int main() -{ - std::string s = R"TestCodesHere( -print nil + 1 -)TestCodesHere"; - std::list globals; - auto result = MoonP::moonCompile(s, globals, true, false); - if (!result.first.empty()) { - std::cout << result.first << '\n'; - } else { - std::cout << result.second << '\n'; - } - std::cout << "globals:\n"; - for (const auto& var : globals) { - std::cout << var.name << '\n'; - } - return 0; -} diff --git a/MoonParser/parser.cpp b/MoonParser/parser.cpp deleted file mode 100644 index 03857c6..0000000 --- a/MoonParser/parser.cpp +++ /dev/null @@ -1,1430 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#include "parser.hpp" - - -namespace parserlib { - - -//internal map from rules to parse procs -typedef std::unordered_map _parse_proc_map_t; - -//on exit, it deletes the parse proc map -static _parse_proc_map_t& _get_parse_proc_map() { - static _parse_proc_map_t _parse_proc_map; - return _parse_proc_map; -} - - -//get the parse proc from the map -static parse_proc _get_parse_proc(rule *r) { - _parse_proc_map_t& _parse_proc_map = _get_parse_proc_map(); - _parse_proc_map_t::iterator it = _parse_proc_map.find(r); - if (it == _parse_proc_map.end()) return 0; - return it->second; -} - - -//internal private class that manages access to the public classes' internals. -class _private { -public: - //get the internal expression object from the expression. - static _expr *get_expr(const expr &e) { - return e.m_expr; - } - - //create new expression from given expression - static expr construct_expr(_expr *e) { - return e; - } - - //get the internal expression object from the rule. - static _expr *get_expr(rule &r) { - return r.m_expr; - } - - //get the internal parse proc from the rule. - static parse_proc get_parse_proc(rule &r) { - return r.m_parse_proc; - } -}; - - -class _context; - - -//parser state -class _state { -public: - //position - pos m_pos; - - //size of match vector - size_t m_matches; - - //constructor - _state(_context &con); -}; - - -//match -class _match { -public: - //rule matched - rule *m_rule; - - //begin position - pos m_begin; - - //end position - pos m_end; - - //null constructor - _match() {} - - //constructor from parameters - _match(rule *r, const pos &b, const pos &e) : - m_rule(r), - m_begin(b), - m_end(e) - { - } -}; - - -//match vector -typedef std::vector<_match> _match_vector; - - -//parsing context -class _context { -public: - //user data - void* m_user_data; - - //current position - pos m_pos; - - //error position - pos m_error_pos; - - //input begin - input::iterator m_begin; - - //input end - input::iterator m_end; - - //matches - _match_vector m_matches; - - //constructor - _context(input &i, void* ud) : - m_user_data(ud), - m_pos(i), - m_error_pos(i), - m_begin(i.begin()), - m_end(i.end()) - { - } - - //check if the end is reached - bool end() const { - return m_pos.m_it == m_end; - } - - //get the current symbol - input::value_type symbol() const { - assert(!end()); - return *m_pos.m_it; - } - - //set the longest possible error - void set_error_pos() { - if (m_pos.m_it > m_error_pos.m_it) { - m_error_pos = m_pos; - } - } - - //next column - void next_col() { - ++m_pos.m_it; - ++m_pos.m_col; - } - - //next line - void next_line() { - ++m_pos.m_line; - m_pos.m_col = 1; - } - - //restore the state - void restore(const _state &st) { - m_pos = st.m_pos; - m_matches.resize(st.m_matches); - } - - //parse non-term rule. - bool parse_non_term(rule &r); - - //parse term rule. - bool parse_term(rule &r); - - //execute all the parse procs - void do_parse_procs(void *d) const { - for(_match_vector::const_iterator it = m_matches.begin(); - it != m_matches.end(); - ++it) - { - const _match &m = *it; - parse_proc p = _private::get_parse_proc(*m.m_rule); - p(m.m_begin, m.m_end, d); - } - } - -private: - //parse non-term rule. - bool _parse_non_term(rule &r); - - //parse term rule. - bool _parse_term(rule &r); -}; - - -//base class for expressions -class _expr { -public: - //destructor. - virtual ~_expr() { - } - - //parse with whitespace - virtual bool parse_non_term(_context &con) const = 0; - - //parse terminal - virtual bool parse_term(_context &con) const = 0; -}; - - -//single character expression. -class _char : public _expr { -public: - //constructor. - _char(char c) : - m_char(c) - { - } - - //parse with whitespace - virtual bool parse_non_term(_context &con) const { - return _parse(con); - } - - //parse terminal - virtual bool parse_term(_context &con) const { - return _parse(con); - } - -private: - //character - input::value_type m_char; - - //internal parse - bool _parse(_context &con) const { - if (!con.end()) { - input::value_type ch = con.symbol(); - if (ch == m_char) { - con.next_col(); - return true; - } - } - con.set_error_pos(); - return false; - } -}; - - -//string expression. -class _string : public _expr { -public: - //constructor from ansi string. - _string(const char *s) : - m_string(Converter{}.from_bytes(s)) - { - } - - //parse with whitespace - virtual bool parse_non_term(_context &con) const { - return _parse(con); - } - - //parse terminal - virtual bool parse_term(_context &con) const { - return _parse(con); - } - -private: - //string - input m_string; - - //parse the string - bool _parse(_context &con) const { - for(input::const_iterator it = m_string.begin(), - end = m_string.end();;) - { - if (it == end) return true; - if (con.end()) break; - if (con.symbol() != *it) break; - ++it; - con.next_col(); - } - con.set_error_pos(); - return false; - } -}; - - -//set expression. -class _set : public _expr { -public: - //constructor from ansi string. - _set(const char *s) { - auto str = Converter{}.from_bytes(s); - for (auto ch : str) { - _add(ch); - } - } - - //constructor from range. - _set(int min, int max) { - assert(min >= 0); - assert(min <= max); - m_quick_set.resize((size_t)max + 1U); - for(; min <= max; ++min) { - m_quick_set[(size_t)min] = true; - } - } - - //parse with whitespace - virtual bool parse_non_term(_context &con) const { - return _parse(con); - } - - //parse terminal - virtual bool parse_term(_context &con) const { - return _parse(con); - } - -private: - //set is kept as an array of flags, for quick access - std::vector m_quick_set; - std::unordered_set m_large_set; - - //add character - void _add(size_t i) { - if (i <= m_quick_set.size() || i <= 255) { - if (i >= m_quick_set.size()) { - m_quick_set.resize(i + 1); - } - m_quick_set[i] = true; - } else { - m_large_set.insert(i); - } - } - - //internal parse - bool _parse(_context &con) const { - if (!con.end()) { - size_t ch = con.symbol(); - if (ch < m_quick_set.size()) { - if (m_quick_set[ch]) { - con.next_col(); - return true; - } - } else if (m_large_set.find(ch) != m_large_set.end()) { - con.next_col(); - return true; - } - } - con.set_error_pos(); - return false; - } -}; - - -//base class for unary expressions -class _unary : public _expr { -public: - //constructor. - _unary(_expr *e) : - m_expr(e) - { - } - - //destructor. - virtual ~_unary() { - delete m_expr; - } - -protected: - //expression - _expr *m_expr; -}; - - -//terminal -class _term : public _unary { -public: - //constructor. - _term(_expr *e) : - _unary(e) - { - } - - //parse with whitespace - virtual bool parse_non_term(_context &con) const { - return m_expr->parse_term(con); - } - - //parse terminal - virtual bool parse_term(_context &con) const { - return m_expr->parse_term(con); - } -}; - - -//user -class _user : public _unary { -public: - //constructor. - _user(_expr *e, const user_handler &callback) : - _unary(e), - m_handler(callback) - { - } - - //parse with whitespace - virtual bool parse_non_term(_context &con) const { - pos pos = con.m_pos; - if (m_expr->parse_non_term(con)) { - item_t item = {pos.m_it, con.m_pos.m_it, con.m_user_data}; - return m_handler(item); - } - return false; - } - - //parse terminal - virtual bool parse_term(_context &con) const { - pos pos = con.m_pos; - if (m_expr->parse_term(con)) { - item_t item = {pos.m_it, con.m_pos.m_it, con.m_user_data}; - return m_handler(item); - } - return false; - } -private: - user_handler m_handler; -}; - - -//loop 0 -class _loop0 : public _unary { -public: - //constructor. - _loop0(_expr *e) : - _unary(e) - { - } - - //parse with whitespace - virtual bool parse_non_term(_context &con) const { - //if parsing of the first fails, restore the context and stop - _state st(con); - if (!m_expr->parse_non_term(con)) { - con.restore(st); - return true; - } - - //parse the rest - for(;;) { - _state st(con); - if (!m_expr->parse_non_term(con)) { - con.restore(st); - break; - } - } - - return true; - } - - //parse terminal - virtual bool parse_term(_context &con) const { - //if parsing of the first fails, restore the context and stop - _state st(con); - if (!m_expr->parse_term(con)) { - con.restore(st); - return true; - } - - //parse the rest until no more parsing is possible - for(;;) { - _state st(con); - if (!m_expr->parse_term(con)) { - con.restore(st); - break; - } - } - - return true; - } -}; - - -//loop 1 -class _loop1 : public _unary { -public: - //constructor. - _loop1(_expr *e) : - _unary(e) - { - } - - //parse with whitespace - virtual bool parse_non_term(_context &con) const { - //parse the first; if the first fails, stop - if (!m_expr->parse_non_term(con)) return false; - - //parse the rest until no more parsing is possible - for(;;) { - _state st(con); - if (!m_expr->parse_non_term(con)) { - con.restore(st); - break; - } - } - - return true; - } - - //parse terminal - virtual bool parse_term(_context &con) const { - //parse the first; if the first fails, stop - if (!m_expr->parse_term(con)) return false; - - //parse the rest until no more parsing is possible - for(;;) { - _state st(con); - if (!m_expr->parse_term(con)) { - con.restore(st); - break; - } - } - - return true; - } -}; - - -//optional -class _optional : public _unary { -public: - //constructor. - _optional(_expr *e) : - _unary(e) - { - } - - //parse with whitespace - virtual bool parse_non_term(_context &con) const { - _state st(con); - if (!m_expr->parse_non_term(con)) con.restore(st); - return true; - } - - //parse terminal - virtual bool parse_term(_context &con) const { - _state st(con); - if (!m_expr->parse_term(con)) con.restore(st); - return true; - } -}; - - -//and -class _and : public _unary { -public: - //constructor. - _and(_expr *e) : - _unary(e) - { - } - - //parse with whitespace - virtual bool parse_non_term(_context &con) const { - _state st(con); - bool ok = m_expr->parse_non_term(con); - con.restore(st); - return ok; - } - - //parse terminal - virtual bool parse_term(_context &con) const { - _state st(con); - bool ok = m_expr->parse_term(con); - con.restore(st); - return ok; - } -}; - - -//not -class _not : public _unary { -public: - //constructor. - _not(_expr *e) : - _unary(e) - { - } - - //parse with whitespace - virtual bool parse_non_term(_context &con) const { - _state st(con); - bool ok = !m_expr->parse_non_term(con); - con.restore(st); - return ok; - } - - //parse terminal - virtual bool parse_term(_context &con) const { - _state st(con); - bool ok = !m_expr->parse_term(con); - con.restore(st); - return ok; - } -}; - - -//newline -class _nl : public _unary { -public: - //constructor. - _nl(_expr *e) : - _unary(e) - { - } - - //parse with whitespace - virtual bool parse_non_term(_context &con) const { - if (!m_expr->parse_non_term(con)) return false; - con.next_line(); - return true; - } - - //parse terminal - virtual bool parse_term(_context &con) const { - if (!m_expr->parse_term(con)) return false; - con.next_line(); - return true; - } -}; - - -//base class for binary expressions -class _binary : public _expr { -public: - //constructor. - _binary(_expr *left, _expr *right) : - m_left(left), m_right(right) - { - } - - //destructor. - virtual ~_binary() { - delete m_left; - delete m_right; - } - -protected: - //left and right expressions - _expr *m_left, *m_right; -}; - - -//sequence -class _seq : public _binary { -public: - //constructor. - _seq(_expr *left, _expr *right) : - _binary(left, right) - { - } - - //parse with whitespace - virtual bool parse_non_term(_context &con) const { - if (!m_left->parse_non_term(con)) return false; - return m_right->parse_non_term(con); - } - - //parse terminal - virtual bool parse_term(_context &con) const { - if (!m_left->parse_term(con)) return false; - return m_right->parse_term(con); - } -}; - - -//choice -class _choice : public _binary { -public: - //constructor. - _choice(_expr *left, _expr *right) : - _binary(left, right) - { - } - - //parse with whitespace - virtual bool parse_non_term(_context &con) const { - _state st(con); - if (m_left->parse_non_term(con)) return true; - con.restore(st); - return m_right->parse_non_term(con); - } - - //parse terminal - virtual bool parse_term(_context &con) const { - _state st(con); - if (m_left->parse_term(con)) return true; - con.restore(st); - return m_right->parse_term(con); - } -}; - - -//reference to rule -class _ref : public _expr { -public: - //constructor. - _ref(rule &r) : - m_rule(r) - { - } - - //parse with whitespace - virtual bool parse_non_term(_context &con) const { - return con.parse_non_term(m_rule); - } - - //parse terminal - virtual bool parse_term(_context &con) const { - return con.parse_term(m_rule); - } - -private: - //reference - rule &m_rule; -}; - - -//eof -class _eof : public _expr { -public: - //parse with whitespace - virtual bool parse_non_term(_context &con) const { - return parse_term(con); - } - - //parse terminal - virtual bool parse_term(_context &con) const { - return con.end(); - } -}; - - -//any -class _any : public _expr { -public: - //parse with whitespace - virtual bool parse_non_term(_context &con) const { - return parse_term(con); - } - - //parse terminal - virtual bool parse_term(_context &con) const { - if (!con.end()) { - con.next_col(); - return true; - } - con.set_error_pos(); - return false; - } -}; - - -//true -class _true : public _expr { -public: - //parse with whitespace - virtual bool parse_non_term(_context &con) const { - return true; - } - - //parse terminal - virtual bool parse_term(_context &con) const { - return true; - } -}; - - -//false -class _false: public _expr { -public: - //parse with whitespace - virtual bool parse_non_term(_context &con) const { - return false; - } - - //parse terminal - virtual bool parse_term(_context &con) const { - return false; - } -}; - -//exception thrown when left recursion terminates successfully -struct _lr_ok { - rule *m_rule; - _lr_ok(rule *r) : m_rule(r) {} -}; - - -//constructor -_state::_state(_context &con) : - m_pos(con.m_pos), - m_matches(con.m_matches.size()) -{ -} - - -//parse non-term rule. -bool _context::parse_non_term(rule &r) { - //save the state of the rule - rule::_state old_state = r.m_state; - - //success/failure result - bool ok; - - //compute the new position - size_t new_pos = m_pos.m_it - m_begin; - - //check if we have left recursion - bool lr = new_pos == r.m_state.m_pos; - - //update the rule's state - r.m_state.m_pos = new_pos; - - //handle the mode of the rule - switch (r.m_state.m_mode) { - //normal parse - case rule::_PARSE: - if (lr) { - //first try to parse the rule by rejecting it, so alternative branches are examined - r.m_state.m_mode = rule::_REJECT; - ok = _parse_non_term(r); - - //if the first try is successful, try accepting the rule, - //so other elements of the sequence are parsed - if (ok) { - r.m_state.m_mode = rule::_ACCEPT; - - //loop until no more parsing can be done - for(;;) { - //store the correct state, in order to backtrack if the call fails - _state st(*this); - - //update the rule position to the current position, - //because at this state the rule is resolving the left recursion - r.m_state.m_pos = m_pos.m_it - m_begin; - - //if parsing fails, restore the last good state and stop - if (!_parse_non_term(r)) { - restore(st); - break; - } - } - - //since the left recursion was resolved successfully, - //return via a non-local exit - r.m_state = old_state; - throw _lr_ok(r.this_ptr()); - } - } - else { - try { - ok = _parse_non_term(r); - } - catch (const _lr_ok &ex) { - //since left recursions may be mutual, we must test which rule's left recursion - //was ended successfully - if (ex.m_rule == r.this_ptr()) { - ok = true; - } - else { - r.m_state = old_state; - throw; - } - } - } - break; - - //reject the left recursive rule - case rule::_REJECT: - if (lr) { - ok = false; - } - else { - r.m_state.m_mode = rule::_PARSE; - ok = _parse_non_term(r); - r.m_state.m_mode = rule::_REJECT; - } - break; - - //accept the left recursive rule - case rule::_ACCEPT: - if (lr) { - ok = true; - } - else { - r.m_state.m_mode = rule::_PARSE; - ok = _parse_non_term(r); - r.m_state.m_mode = rule::_ACCEPT; - } - break; - } - - //restore the rule's state - r.m_state = old_state; - - return ok; -} - - -//parse term rule. -bool _context::parse_term(rule &r) { - //save the state of the rule - rule::_state old_state = r.m_state; - - //success/failure result - bool ok; - - //compute the new position - size_t new_pos = m_pos.m_it - m_begin; - - //check if we have left recursion - bool lr = new_pos == r.m_state.m_pos; - - //update the rule's state - r.m_state.m_pos = new_pos; - - //handle the mode of the rule - switch (r.m_state.m_mode) { - //normal parse - case rule::_PARSE: - if (lr) { - //first try to parse the rule by rejecting it, so alternative branches are examined - r.m_state.m_mode = rule::_REJECT; - ok = _parse_term(r); - - //if the first try is successful, try accepting the rule, - //so other elements of the sequence are parsed - if (ok) { - r.m_state.m_mode = rule::_ACCEPT; - - //loop until no more parsing can be done - for(;;) { - //store the correct state, in order to backtrack if the call fails - _state st(*this); - - //update the rule position to the current position, - //because at this state the rule is resolving the left recursion - r.m_state.m_pos = m_pos.m_it - m_begin; - - //if parsing fails, restore the last good state and stop - if (!_parse_term(r)) { - restore(st); - break; - } - } - - //since the left recursion was resolved successfully, - //return via a non-local exit - r.m_state = old_state; - throw _lr_ok(r.this_ptr()); - } - } - else { - try { - ok = _parse_term(r); - } - catch (const _lr_ok &ex) { - //since left recursions may be mutual, we must test which rule's left recursion - //was ended successfully - if (ex.m_rule == r.this_ptr()) { - ok = true; - } - else { - r.m_state = old_state; - throw; - } - } - } - break; - - //reject the left recursive rule - case rule::_REJECT: - if (lr) { - ok = false; - } - else { - r.m_state.m_mode = rule::_PARSE; - ok = _parse_term(r); - r.m_state.m_mode = rule::_REJECT; - } - break; - - //accept the left recursive rule - case rule::_ACCEPT: - if (lr) { - ok = true; - } - else { - r.m_state.m_mode = rule::_PARSE; - ok = _parse_term(r); - r.m_state.m_mode = rule::_ACCEPT; - } - break; - } - - //restore the rule's state - r.m_state = old_state; - - return ok; -} - - -//parse non-term rule internal. -bool _context::_parse_non_term(rule &r) { - bool ok; - if (_private::get_parse_proc(r)) { - pos b = m_pos; - ok = _private::get_expr(r)->parse_non_term(*this); - if (ok) { - m_matches.push_back(_match(r.this_ptr(), b, m_pos)); - } - } - else { - ok = _private::get_expr(r)->parse_non_term(*this); - } - return ok; -} - - -//parse term rule internal. -bool _context::_parse_term(rule &r) { - bool ok; - if (_private::get_parse_proc(r)) { - pos b = m_pos; - ok = _private::get_expr(r)->parse_term(*this); - if (ok) { - m_matches.push_back(_match(r.this_ptr(), b, m_pos)); - } - } - else { - ok = _private::get_expr(r)->parse_term(*this); - } - return ok; -} - - -//get syntax error -static error _syntax_error(_context &con) { - return error(con.m_error_pos, con.m_error_pos, ERROR_SYNTAX_ERROR); -} - - -//get eof error -static error _eof_error(_context &con) { - return error(con.m_error_pos, con.m_error_pos, ERROR_INVALID_EOF); -} - - -/** constructor from input. - @param i input. - */ -pos::pos(input &i) : - m_it(i.begin()), - m_line(1), - m_col(1) -{ -} - - -/** character terminal constructor. - @param c character. - */ -expr::expr(char c) : - m_expr(new _char(c)) -{ -} - - -/** null-terminated string terminal constructor. - @param s null-terminated string. - */ -expr::expr(const char *s) : - m_expr(new _string(s)) -{ -} - - -/** rule reference constructor. - @param r rule. - */ -expr::expr(rule &r) : - m_expr(new _ref(r)) -{ -} - - -/** creates a zero-or-more loop out of this expression. - @return a zero-or-more loop expression. - */ -expr expr::operator *() const { - return _private::construct_expr(new _loop0(m_expr)); -} - - -/** creates a one-or-more loop out of this expression. - @return a one-or-more loop expression. - */ -expr expr::operator +() const { - return _private::construct_expr(new _loop1(m_expr)); -} - - -/** creates an optional out of this expression. - @return an optional expression. - */ -expr expr::operator -() const { - return _private::construct_expr(new _optional(m_expr)); -} - - -/** creates an AND-expression. - @return an AND-expression. - */ -expr expr::operator &() const { - return _private::construct_expr((new _and(m_expr))); -} - - -/** creates a NOT-expression. - @return a NOT-expression. - */ -expr expr::operator !() const { - return _private::construct_expr(new _not(m_expr)); -} - - -/** constructor. - @param b begin position. - @param e end position. - */ -input_range::input_range(const pos &b, const pos &e) : -m_begin(b), -m_end(e) {} - - -/** constructor. - @param b begin position. - @param e end position. - @param t error type. - */ -error::error(const pos &b, const pos &e, int t) : -input_range(b, e), -m_type(t) {} - - -/** compare on begin position. - @param e the other error to compare this with. - @return true if this comes before the previous error, false otherwise. - */ -bool error::operator < (const error &e) const { - return m_begin.m_it < e.m_begin.m_it; -} - - -/** character terminal constructor. - @param c character. - */ -rule::rule(char c) : - m_expr(new _char(c)) -{ - m_parse_proc = _get_parse_proc(this); -} - - -/** null-terminated string terminal constructor. - @param s null-terminated string. - */ -rule::rule(const char *s) : - m_expr(new _string(s)) -{ - m_parse_proc = _get_parse_proc(this); -} - - -/** constructor from expression. - @param e expression. - */ -rule::rule(const expr &e) : - m_expr(_private::get_expr(e)) -{ - m_parse_proc = _get_parse_proc(this); -} - - -/** constructor from rule. - @param r rule. - */ -rule::rule(rule &r) : - m_expr(new _ref(r)), - m_parse_proc(0) -{ - m_parse_proc = _get_parse_proc(this); -} - - -/** invalid constructor from rule (required by gcc). - @param r rule. - @exception std::logic_error always thrown. - */ -rule::rule(const rule &r) { - throw std::logic_error("invalid operation"); -} - - -/** deletes the internal object that represents the expression. - */ -rule::~rule() { - delete m_expr; -} - - -/** creates a zero-or-more loop out of this rule. - @return a zero-or-more loop rule. - */ -expr rule::operator *() { - return _private::construct_expr(new _loop0(new _ref(*this))); -} - - -/** creates a one-or-more loop out of this rule. - @return a one-or-more loop rule. - */ -expr rule::operator +() { - return _private::construct_expr(new _loop1(new _ref(*this))); -} - - -/** creates an optional out of this rule. - @return an optional rule. - */ -expr rule::operator -() { - return _private::construct_expr(new _optional(new _ref(*this))); -} - - -/** creates an AND-expression out of this rule. - @return an AND-expression out of this rule. - */ -expr rule::operator &() { - return _private::construct_expr(new _and(new _ref(*this))); -} - - -/** creates a NOT-expression out of this rule. - @return a NOT-expression out of this rule. - */ -expr rule::operator !() { - return _private::construct_expr(new _not(new _ref(*this))); -} - - -/** sets the parse procedure. - @param p procedure. - */ -void rule::set_parse_proc(parse_proc p) { - assert(p); - m_parse_proc = p; - _parse_proc_map_t& _parse_proc_map = _get_parse_proc_map(); - _parse_proc_map[this] = p; -} - - -/** creates a sequence of expressions. - @param left left operand. - @param right right operand. - @return an expression which parses a sequence. - */ -expr operator >> (const expr &left, const expr &right) { - return _private::construct_expr( - new _seq(_private::get_expr(left), _private::get_expr(right))); -} - - -/** creates a choice of expressions. - @param left left operand. - @param right right operand. - @return an expression which parses a choice. - */ -expr operator | (const expr &left, const expr &right) { - return _private::construct_expr( - new _choice(_private::get_expr(left), _private::get_expr(right))); -} - - -/** converts a parser expression into a terminal. - @param e expression. - @return an expression which parses a terminal. - */ -expr term(const expr &e) { - return _private::construct_expr( - new _term(_private::get_expr(e))); -} - - -/** creates a set expression from a null-terminated string. - @param s null-terminated string with characters of the set. - @return an expression which parses a single character out of a set. - */ -expr set(const char *s) { - return _private::construct_expr(new _set(s)); -} - - -/** creates a range expression. - @param min min character. - @param max max character. - @return an expression which parses a single character out of range. - */ -expr range(int min, int max) { - return _private::construct_expr(new _set(min, max)); -} - - -/** creates an expression which increments the line counter - and resets the column counter when the given expression - is parsed successfully; used for newline characters. - @param e expression to wrap into a newline parser. - @return an expression that handles newlines. - */ -expr nl(const expr &e) { - return _private::construct_expr(new _nl(_private::get_expr(e))); -} - - -/** creates an expression which tests for the end of input. - @return an expression that handles the end of input. - */ -expr eof() { - return _private::construct_expr(new _eof()); -} - - -/** creates a not expression. - @param e expression. - @return the appropriate expression. - */ -expr not_(const expr &e) { - return !e; -} - - -/** creates an and expression. - @param e expression. - @return the appropriate expression. - */ -expr and_(const expr &e) { - return &e; -} - - -/** creates an expression that parses any character. - @return the appropriate expression. - */ -expr any() { - return _private::construct_expr(new _any()); -} - - -/** parsing succeeds without consuming any input. -*/ -expr true_() { - return _private::construct_expr(new _true()); -} - - -/** parsing fails without consuming any input. -*/ -expr false_() { - return _private::construct_expr(new _false()); -} - - -/** parse with target expression and let user handle result. -*/ -expr user(const expr &e, const user_handler& handler) { - return _private::construct_expr(new _user(_private::get_expr(e), handler)); -} - - -/** parses the given input. - The parse procedures of each rule parsed are executed - before this function returns, if parsing succeeds. - @param i input. - @param g root rule of grammar. - @param el list of errors. - @param d user data, passed to the parse procedures. - @return true on parsing success, false on failure. - */ -bool parse(input &i, rule &g, error_list &el, void *d, void* ud) { - //prepare context - _context con(i, ud); - - //parse grammar - if (!con.parse_non_term(g)) { - el.push_back(_syntax_error(con)); - return false; - } - - //if end is not reached, there was an error - if (!con.end()) { - if (con.m_error_pos.m_it < con.m_end) { - el.push_back(_syntax_error(con)); - } - else { - el.push_back(_eof_error(con)); - } - return false; - } - - //success; execute the parse procedures - con.do_parse_procs(d); - return true; -} - - -} //namespace parserlib diff --git a/MoonParser/parser.hpp b/MoonParser/parser.hpp deleted file mode 100644 index cbf0168..0000000 --- a/MoonParser/parser.hpp +++ /dev/null @@ -1,425 +0,0 @@ -#pragma once - - -//gcc chokes without rule::rule(const rule &), -//msvc complains when rule::rule(const rule &) is defined. -#ifdef _MSC_VER -#pragma warning (disable: 4521) -#endif - - -#include -#include -#include -#include -#include -#include - -namespace parserlib { - -// const str hash helper functions -inline constexpr size_t hash(char const* input) -{ - return *input ? *input + 33ull * hash(input + 1) : 5381; -} -inline size_t hash(const char* input, int size, int index) -{ - return index < size ? input[index] + 33ull * hash(input, size, index + 1) : 5381; -} -inline size_t constexpr operator"" _id(const char* s, size_t) -{ - return hash(s); -} - -///type of the parser's input. -typedef std::basic_string input; -typedef input::iterator input_it; -typedef std::wstring_convert> Converter; - -class _private; -class _expr; -class _context; -class rule; - - -struct item_t -{ - input_it begin; - input_it end; - void* user_data; -}; -typedef std::function user_handler; - - -///position into the input. -class pos { -public: - ///interator into the input. - input::iterator m_it; - - ///line. - int m_line; - - ///column. - int m_col; - - ///null constructor. - pos():m_line(-1),m_col(0) {} - - /** constructor from input. - @param i input. - */ - pos(input &i); -}; - - -/** a grammar expression. - */ -class expr { -public: - /** character terminal constructor. - @param c character. - */ - expr(char c); - - /** null-terminated string terminal constructor. - @param s null-terminated string. - */ - expr(const char *s); - - /** rule reference constructor. - @param r rule. - */ - expr(rule &r); - - /** creates a zero-or-more loop out of this expression. - @return a zero-or-more loop expression. - */ - expr operator *() const; - - /** creates a one-or-more loop out of this expression. - @return a one-or-more loop expression. - */ - expr operator +() const; - - /** creates an optional out of this expression. - @return an optional expression. - */ - expr operator -() const; - - /** creates an AND-expression. - @return an AND-expression. - */ - expr operator &() const; - - /** creates a NOT-expression. - @return a NOT-expression. - */ - expr operator !() const; - -private: - //internal expression - _expr *m_expr; - - //internal constructor from internal expression - expr(_expr *e) : m_expr(e) {} - - //assignment not allowed - expr &operator = (expr &); - - friend class _private; -}; - - -/** type of procedure to invoke when a rule is successfully parsed. - @param b begin position of input. - @param e end position of input. - @param d pointer to user data. - */ -typedef void (*parse_proc)(const pos &b, const pos &e, void *d); - - -///input range. -class input_range { -public: - virtual ~input_range() {} - - ///begin position. - pos m_begin; - - ///end position. - pos m_end; - - ///empty constructor. - input_range() {} - - /** constructor. - @param b begin position. - @param e end position. - */ - input_range(const pos &b, const pos &e); -}; - - -///enum with error types. -enum ERROR_TYPE { - ///syntax error - ERROR_SYNTAX_ERROR = 1, - - ///invalid end of file - ERROR_INVALID_EOF, - - ///first user error - ERROR_USER = 100 -}; - - -///error. -class error : public input_range { -public: - ///type - int m_type; - - /** constructor. - @param b begin position. - @param e end position. - @param t type. - */ - error(const pos &b, const pos &e, int t); - - /** compare on begin position. - @param e the other error to compare this with. - @return true if this comes before the previous error, false otherwise. - */ - bool operator < (const error &e) const; -}; - - -///type of error list. -typedef std::list error_list; - - -/** represents a rule. - */ -class rule { -public: - /** character terminal constructor. - @param c character. - */ - rule(char c); - - /** null-terminated string terminal constructor. - @param s null-terminated string. - */ - rule(const char *s); - - /** constructor from expression. - @param e expression. - */ - rule(const expr &e); - - /** constructor from rule. - @param r rule. - */ - rule(rule &r); - - /** invalid constructor from rule (required by gcc). - @param r rule. - @exception std::logic_error always thrown. - */ - rule(const rule &r); - - /** deletes the internal object that represents the expression. - */ - ~rule(); - - /** creates a zero-or-more loop out of this rule. - @return a zero-or-more loop rule. - */ - expr operator *(); - - /** creates a one-or-more loop out of this rule. - @return a one-or-more loop rule. - */ - expr operator +(); - - /** creates an optional out of this rule. - @return an optional rule. - */ - expr operator -(); - - /** creates an AND-expression out of this rule. - @return an AND-expression out of this rule. - */ - expr operator &(); - - /** creates a NOT-expression out of this rule. - @return a NOT-expression out of this rule. - */ - expr operator !(); - - /** sets the parse procedure. - @param p procedure. - */ - void set_parse_proc(parse_proc p); - - /** get the this ptr (since operator & is overloaded). - @return pointer to this. - */ - rule *this_ptr() { return this; } - -private: - //mode - enum _MODE { - _PARSE, - _REJECT, - _ACCEPT - }; - - //state - struct _state { - //position in source code, relative to start - size_t m_pos; - - //mode - _MODE m_mode; - - //constructor - _state(size_t pos = -1, _MODE mode = _PARSE) : - m_pos(pos), m_mode(mode) {} - }; - - //internal expression - _expr *m_expr; - - //associated parse procedure. - parse_proc m_parse_proc; - - //state - _state m_state; - - //assignment not allowed - rule &operator = (rule &); - - friend class _private; - friend class _context; -}; - - -/** creates a sequence of expressions. - @param left left operand. - @param right right operand. - @return an expression which parses a sequence. - */ -expr operator >> (const expr &left, const expr &right); - - -/** creates a choice of expressions. - @param left left operand. - @param right right operand. - @return an expression which parses a choice. - */ -expr operator | (const expr &left, const expr &right); - - -/** converts a parser expression into a terminal. - @param e expression. - @return an expression which parses a terminal. - */ -expr term(const expr &e); - - -/** creates a set expression from a null-terminated string. - @param s null-terminated string with characters of the set. - @return an expression which parses a single character out of a set. - */ -expr set(const char *s); - - -/** creates a range expression. - @param min min character. - @param max max character. - @return an expression which parses a single character out of range. - */ -expr range(int min, int max); - - -/** creates an expression which increments the line counter - and resets the column counter when the given expression - is parsed successfully; used for newline characters. - @param e expression to wrap into a newline parser. - @return an expression that handles newlines. - */ -expr nl(const expr &e); - - -/** creates an expression which tests for the end of input. - @return an expression that handles the end of input. - */ -expr eof(); - - -/** creates a not expression. - @param e expression. - @return the appropriate expression. - */ -expr not_(const expr &e); - - -/** creates an and expression. - @param e expression. - @return the appropriate expression. - */ -expr and_(const expr &e); - - -/** creates an expression that parses any character. - @return the appropriate expression. - */ -expr any(); - - -/** parsing succeeds without consuming any input. - */ -expr true_(); - - -/** parsing fails without consuming any input. -*/ -expr false_(); - - -/** parse with target expression and let user handle result. -*/ -expr user(const expr &e, const user_handler& handler); - - -/** parses the given input. - The parse procedures of each rule parsed are executed - before this function returns, if parsing succeeds. - @param i input. - @param g root rule of grammar. - @param el list of errors. - @param d user data, passed to the parse procedures. - @return true on parsing success, false on failure. - */ -bool parse(input &i, rule &g, error_list &el, void *d, void* ud); - - -/** output the specific input range to the specific stream. - @param stream stream. - @param ir input range. - @return the stream. - */ -template T &operator << (T &stream, const input_range &ir) { - for(input::const_iterator it = ir.m_begin.m_it; - it != ir.m_end.m_it; - ++it) - { - stream << (typename T::char_type)*it; - } - return stream; -} - - -} //namespace parserlib -- cgit v1.2.3-55-g6feb