From fabc309a0a0a6f210a8a7ed8f0d1f8498971f409 Mon Sep 17 00:00:00 2001 From: Li Jin Date: Sun, 8 Sep 2019 00:28:49 +0800 Subject: completing moonscript compiler with c++. --- MoonParser/ast.cpp | 127 +++++++- MoonParser/ast.hpp | 36 ++- MoonParser/moon_ast.cpp | 822 +++++++++++++++++++++++++++++++++++++++++++---- MoonParser/moon_ast.h | 238 +++++++------- MoonParser/moon_parser.h | 2 +- MoonParser/parser.hpp | 13 + 6 files changed, 1052 insertions(+), 186 deletions(-) (limited to 'MoonParser') diff --git a/MoonParser/ast.cpp b/MoonParser/ast.cpp index 739e02c..6217f3e 100644 --- a/MoonParser/ast.cpp +++ b/MoonParser/ast.cpp @@ -10,13 +10,19 @@ static ast_container *_current = 0; int ast_type_id = 0; +traversal ast_node::traverse(const std::function& func) { + return func(this); +} -bool ast_node::visit(const std::function& begin, - const std::function& end) -{ - return begin(this) || end(this); +ast_node* ast_node::getByPath(std::initializer_list) { + return nullptr; } +void ast_node::eachChild(const std::function&) { } + +bool ast_node::visitChild(const std::function&) { + return false; +} /** sets the container under construction to be this. */ @@ -48,28 +54,123 @@ void ast_container::construct(ast_stack &st) { } } -bool ast_container::visit(const std::function& begin, - const std::function& end) -{ - bool result = begin(this); - if (result) return true; +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()->visit(begin, end)) { + 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; +} + +ast_node* ast_container::getByPath(std::initializer_list paths) { + ast_node* current = this; + auto it = paths.begin(); + while (it != paths.end()) { + ast_node* findNode = nullptr; + current->visitChild([&](ast_node* node) { + if (node->getId() == *it) { + findNode = node; return true; } + return false; + }); + if (findNode) { + current = findNode; + } else { + current = nullptr; + break; + } + ++it; + } + return current; +} + +void ast_container::eachChild(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()) { + func(ptr->get()); + } + } else if (_ast_list* list = ast_cast<_ast_list>(member)) { + for (auto obj : list->objects()) { + if (obj) { + func(obj); + } + } + } + } +} + +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->visit(begin, end)) { - return true; + if (obj) { + if (func(obj)) return true; } } } } - return end(this); + return false; } +ast_node* ast_container::getChild(int index) const { + int i = 0; + const auto& members = this->members(); + for (auto member : members) { + if (_ast_ptr* ptr = ast_cast<_ast_ptr>(member)) { + if (ptr->get()) { + if (i == index) return ptr->get(); + i++; + } + } else if (_ast_list* list = ast_cast<_ast_list>(member)) { + for (auto obj : list->objects()) { + if (obj) { + if (i == index) return obj; + i++; + } + } + } + } + return nullptr; +} + +int ast_container::getChildCount() const { + int count = 0; + const auto& members = this->members(); + for (auto member : members) { + if (_ast_ptr* ptr = ast_cast<_ast_ptr>(member)) { + if (ptr->get()) count++; + } else if (_ast_list* list = ast_cast<_ast_list>(member)) { + for (auto obj : list->objects()) { + if (obj) count++; + } + } + } + return count; +} //register the AST member to the current container. void ast_member::_init() { diff --git a/MoonParser/ast.hpp b/MoonParser/ast.hpp index 1d05779..4d52dfc 100644 --- a/MoonParser/ast.hpp +++ b/MoonParser/ast.hpp @@ -31,6 +31,12 @@ int ast_type() return type; } +enum class traversal { + Continue, + Return, + Stop +}; + /** Base class for AST nodes. */ class ast_node : public input_range { @@ -65,8 +71,19 @@ public: /** interface for visiting AST tree use. */ - virtual bool visit(const std::function& begin, - const std::function& end); + virtual traversal traverse(const std::function& func); + + virtual ast_node* getByPath(std::initializer_list paths); + + virtual void eachChild(const std::function& func); + + virtual bool visitChild(const std::function& func); + + virtual ast_node* getChild(int) const { return nullptr; } + + virtual int getChildCount() const { return 0; } + + virtual size_t getId() const { return "ast_node"_id; } virtual const char* getName() const { return "ast_node"; } @@ -140,8 +157,19 @@ public: */ virtual void construct(ast_stack &st) override; - virtual bool visit(const std::function& begin, - const std::function& end) override; + virtual ast_node* getByPath(std::initializer_list paths) override; + + virtual traversal traverse(const std::function& func) override; + + virtual void eachChild(const std::function& func) override; + + virtual bool visitChild(const std::function& func) override; + + virtual ast_node* getChild(int index) const override; + + virtual int getChildCount() const override; + + virtual size_t getId() const override { return "ast_container"_id; } virtual const char* getName() const override { return "ast_container"; } private: diff --git a/MoonParser/moon_ast.cpp b/MoonParser/moon_ast.cpp index 2a6ca61..4fb0212 100644 --- a/MoonParser/moon_ast.cpp +++ b/MoonParser/moon_ast.cpp @@ -2,23 +2,15 @@ #include #include #include -#include #include +#include +#include +#include +#include +#include +using namespace std::string_view_literals; #include "moon_ast.h" -input& trim(input& s) -{ - s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](input::value_type ch) - { - return !std::isspace(ch); - })); - s.erase(std::find_if(s.rbegin(), s.rend(), [](input::value_type ch) - { - return !std::isspace(ch); - }).base(), s.end()); - return s; -} - const input& AstLeaf::getValue() { if (_value.empty()) @@ -144,50 +136,768 @@ AST_IMPL(BlockEnd) #include -int main() +template +inline std::unique_ptr MakeUnique(Args&&... args) { + return std::unique_ptr(new T(std::forward(args)...)); +} + +inline std::string s(std::string_view sv) { + return std::string(sv); +} + +class MoonCompliler { - std::string s = R"TestCodesHere( -thing = { var: 10, hello: "world", func: => @var } -import hello, \func from thing -)TestCodesHere"; - input i = Converter{}.from_bytes(s); - - error_list el; - BlockEnd_t* root = nullptr; - State st; - if (parse(i, BlockEnd, el, root, &st)) - { - std::cout << "matched!\n"; - int indent = 0; - root->visit([&](ast_node* node) - { - if (std::string("Seperator") != node->getName()) - { - indent++; - for (int i = 0; i < indent; i++) std::cout << " "; - std::cout << "{" << node->getName() << "\n"; - } - return false; - }, [&](ast_node* node) - { - if (std::string("Seperator") != node->getName()) - { - for (int i = 0; i < indent; i++) std::cout << " "; - std::cout << "}\n" ; - indent--; - } - return false; - }); - } - else - { - std::cout << "not matched!\n"; - for (error_list::iterator it = el.begin(); it != el.end(); ++it) - { - const error& err = *it; - std::cout << "line " << err.m_begin.m_line << ", col " << err.m_begin.m_col << ": syntax error\n"; +public: + void complile(const std::string& codes) { + input input = _converter.from_bytes(codes); + error_list el; + BlockEnd_t* root = nullptr; + State st; + if (parse(input, BlockEnd, el, root, &st)) { + std::cout << "matched!\n"; + std::vector out; + root->eachChild([&](ast_node* node) { + switch (node->getId()) { + case "Block"_id: + pushScope(); + transformBlock(node, out); + popScope(); + break; + default: break; + } + }); + std::string result; + if (out.size() == 1) { + result = std::move(out.front()); + } else if (out.size() > 1) { + result = join(out, "\n"); + } + std::cout << result << '\n'; + } else { + std::cout << "not matched!\n"; + for (error_list::iterator it = el.begin(); it != el.end(); ++it) { + const error& err = *it; + std::cout << "line " << err.m_begin.m_line << ", col " << err.m_begin.m_col << ": syntax error\n"; + } + } + } + +private: + Converter _converter; + std::ostringstream _buf; + std::string _newLine = "\n"; + std::vector _lineTable; + struct Scope { + std::unique_ptr> vars; + std::unique_ptr> allows; + }; + std::vector _scopes; + static const std::string Empty; + + void pushScope() { + _scopes.emplace_back(); + _scopes.back().vars = MakeUnique>(); + } + + bool isDefined(const std::string& name, bool checkShadowScope = false) { + 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; + } + if (checkShadowScope && it->allows) break; + } + return isDefined; + } + + void markVarShadowed() { + auto& scope = _scopes.back(); + scope.allows = MakeUnique>(); + } + + 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); + } + + bool addToScope(const std::string& name) { + bool defined = false; + auto& scope = _scopes.back(); + decltype(scope.allows.get()) allows = nullptr; + for (auto it = _scopes.rbegin(); it != _scopes.rend(); ++it) { + if (it->allows) allows = it->allows.get(); + } + if (allows) { + bool shadowed = allows->find(name) == allows->end(); + defined = isDefined(name, shadowed); + } else { + defined = isDefined(name); + } + if (!defined) scope.vars->insert(name); + return !defined; + } + + void popScope() { + _scopes.pop_back(); + } + + const std::string nll(ast_node* node) { + _lineTable.push_back(node->m_begin.m_line); + return _newLine; + } + + const std::string nlr(ast_node* node) { + _lineTable.push_back(node->m_end.m_line); + return _newLine; + } + + std::string indent() { + return std::string(_scopes.size() - 1, '\t'); + } + + std::string clearBuf() { + std::string str = _buf.str(); + _buf.str(""); + _buf.clear(); + return str; + } + + std::string join(const std::vector& items) { + if (items.empty()) return Empty; + else if (items.size() == 1) return items.front(); + return std::accumulate(items.begin()+1, items.end(), items.front(), + [&](const std::string& a, const std::string& b) { return a + b; }); + } + + std::string join(const std::vector& items, std::string_view sep) { + if (items.empty()) return Empty; + else if (items.size() == 1) return items.front(); + std::string sepStr = s(sep); + return std::accumulate(items.begin()+1, items.end(), items.front(), + [&](const std::string& a, const std::string& b) { return a + sepStr + b; }); + } + + std::string toString(ast_node* node) { + auto str = _converter.to_bytes(std::u32string(node->m_begin.m_it, node->m_end.m_it)); + return trim(str); + } + + void noop(ast_node* node, std::vector& out) { + auto str = _converter.to_bytes(std::u32string(node->m_begin.m_it, node->m_end.m_it)); + out.push_back(s("<"sv) + node->getName() + s(">"sv) + trim(str)); + // out.push_back(trim(str)); + } + + void noopnl(ast_node* node, std::vector& out) { + auto str = _converter.to_bytes(std::u32string(node->m_begin.m_it, node->m_end.m_it)); + out.push_back(s("<"sv) + node->getName() + s(">"sv) + trim(str) + nll(node)); + // out.push_back(trim(str) + nll(node)); + } + + void transformBlock(ast_node* block, std::vector& out) { + std::vector temp; + block->eachChild([&](ast_node* node) { + switch (node->getId()) { + case "Line"_id: transformLine(node, temp); break; + default: break; + } + }); + out.push_back(join(temp)); + } + + void transformLine(ast_node* line, std::vector& out) { + line->eachChild([&](ast_node* node) { + switch (node->getId()) { + case "Statement"_id: transformStatement(node, out); break; + default: break; + } + }); + } + + void transformStatement(ast_node* statement, std::vector& out) { + std::vector temp; + auto transformContent = [&](ast_node* node, std::vector& out) { + switch (node->getId()) { + case "Import"_id: transformImport(node, temp); break; + case "While"_id: transformWhile(node, temp); break; + case "With"_id: transformWith(node, temp); break; + case "For"_id: transformFor(node, temp); break; + case "ForEach"_id: transformForEach(node, temp); break; + case "Switch"_id: transformSwitch(node, temp); break; + case "Return"_id: transformReturn(node, temp); break; + case "Local"_id: transformLocal(node, temp); break; + case "Export"_id: transformExport(node, temp); break; + case "BreakLoop"_id: transformBreakLoop(node, temp); break; + case "Assignment"_id: transformAssignment(node, temp); break; + case "ExpList"_id: + transformExpList(node, temp); + temp.back() = indent() + temp.back() + nll(node); + break; + default: break; + } + }; + if (statement->getChildCount() > 1) { + pushScope(); + transformContent(statement->getChild(0), out); + popScope(); + transform_statement_appendix(statement->getChild(1), temp); + } else { + transformContent(statement->getChild(0), out); + } + switch (temp.size()) { + case 1: // body + out.push_back(std::move(temp.front())); + break; + case 2: // body, if + out.push_back(join({std::move(temp[1]), std::move(temp[0]), s("end"sv) + nlr(statement)})); + break; + case 3: // body, if, else + out.push_back(join({std::move(temp[1]), std::move(temp[0]), std::move(temp[2]), s("end"sv) + nlr(statement)})); + break; + } + } + + void transform_statement_appendix(ast_node* appendix, std::vector& out) { + appendix->eachChild([&](ast_node* node) { + switch (node->getId()) { + case "if_else_line"_id: transform_if_else_line(node, out); break; + case "unless_line"_id: transform_unless_line(node, out); break; + case "CompInner"_id: transformCompInner(node, out); break; + default: break; + } + }); + } + + void transform_if_else_line(ast_node* if_else_line, std::vector& out) { + std::vector temp; + if_else_line->eachChild([&](ast_node* node) { + switch (node->getId()) { + case "Exp"_id: + pushScope(); + transformExp(node, temp); + popScope(); + break; + default: break; + } + }); + out.push_back(indent() + s("if "sv) + temp[0] + s(" then"sv) + nll(if_else_line)); + out.push_back(indent() + s("else "sv) + nll(if_else_line) + indent() + '\t' + temp[1] + nll(if_else_line)); + } + + void transformAssignment(ast_node* assignment, std::vector& out) { + std::vector temp; + std::string preDefined; + assignment->eachChild([&](ast_node* node) { + switch (node->getId()) { + case "ExpList"_id: { + std::vector preDefs; + std::vector values; + node->traverse([&](ast_node* child) { + if (child->getId() == "Value"_id) { + auto target = child->getByPath({"ChainValue"_id, "Callable"_id, "Name"_id}); + if (target) { + auto name = toString(target); + if (addToScope(name)) { + preDefs.push_back(name); + } + } + return traversal::Return; + } + return traversal::Continue; + }); + if (!preDefs.empty()) { + preDefined = indent() + s("local "sv) + join(preDefs, ", "sv) + nll(node); + } + transformExpList(node, temp); + break; + } + case "Update"_id: transformUpdate(node, temp); break; + case "Assign"_id: transformAssign(node, temp); break; + default: break; + } + }); + out.push_back(preDefined + indent() + temp[0] + s(" = "sv) + temp[1] + nll(assignment)); + } + + void transformExpList(ast_node* expList, std::vector& out) { + std::vector temp; + expList->eachChild([&](ast_node* node) { + switch (node->getId()) { + case "Exp"_id: transformExp(node, temp); break; + default: break; + } + }); + out.push_back(join(temp, ", "sv)); + } + + void transformExpListLow(ast_node* expListLow, std::vector& out) { + std::vector temp; + expListLow->eachChild([&](ast_node* node) { + switch (node->getId()) { + case "Exp"_id: transformExp(node, temp); break; + default: break; + } + }); + out.push_back(join(temp, ", "sv)); + } + + void transformAssign(ast_node* assign, std::vector& out) { + assign->eachChild([&](ast_node* node) { + switch (node->getId()) { + case "With"_id: transformWith(node, out); break; + case "If"_id: transformIf(node, out); break; + case "Switch"_id: transformSwitch(node, out); break; + case "TableBlock"_id: transformTableBlock(node, out); break; + case "ExpListLow"_id: transformExpListLow(node, out); break; + default: break; + } + }); + } + + void transformExp(ast_node* exp, std::vector& out) { + std::vector temp; + exp->eachChild([&](ast_node* node) { + switch (node->getId()) { + case "Value"_id: transformValue(node, temp); break; + case "exp_op_value"_id: transform_exp_op_value(node, temp); break; + default: break; + } + }); + out.push_back(join(temp, " "sv)); + } + + void transform_exp_op_value(ast_node* exp_op_value, std::vector& out) { + exp_op_value->eachChild([&](ast_node* node) { + switch (node->getId()) { + case "BinaryOperator"_id: transformBinaryOperator(node, out); break; + case "Value"_id: transformValue(node, out); break; + default: break; + } + }); + } + + void transformValue(ast_node* value, std::vector& out) { + value->eachChild([&](ast_node* node) { + switch (node->getId()) { + case "SimpleValue"_id: transformSimpleValue(node, out); break; + case "simple_table"_id: transform_simple_table(node, out); break; + case "ChainValue"_id: transformChainValue(node, out); break; + case "String"_id: transformString(node, out); break; + default: break; + } + }); + } + + void transformChainValue(ast_node* chainValue, std::vector& out) { + std::vector temp; + bool hasInvokeArgs = false; + chainValue->eachChild([&](ast_node* node) { + switch (node->getId()) { + case "Chain"_id: transformChain(node, temp); break; + case "Callable"_id: transformCallable(node, temp); break; + case "InvokeArgs"_id: + hasInvokeArgs = true; + transformInvokeArgs(node, temp); + break; + default: break; + } + }); + out.push_back(hasInvokeArgs ? (temp[0] + s("("sv) + temp[1] + s(")"sv)) : temp[0]); + } + + void transformCallable(ast_node* callable, std::vector& out) { + callable->eachChild([&](ast_node* node) { + switch (node->getId()) { + case "Name"_id: transformName(node, out); break; + case "SelfName"_id: transformSelfName(node, out); break; + case "VarArg"_id: transformVarArg(node, out); break; + case "Parens"_id: transformParens(node, out); break; + default: break; + } + }); + } + + void transformParens(ast_node* parans, std::vector& out) { + std::vector temp; + parans->eachChild([&](ast_node* node) { + switch (node->getId()) { + case "Exp"_id: transformExp(node, temp); break; + default: break; + } + }); + out.push_back(s("("sv) + temp.front() + s(")"sv)); + } + + void transformSimpleValue(ast_node* simpleValue, std::vector& out) { + simpleValue->eachChild([&](ast_node* node) { + switch (node->getId()) { + case "const_value"_id: transform_const_value(node, out); break; + case "If"_id: transformIf(node, out); break; + case "Switch"_id: transformSwitch(node, out); break; + case "With"_id: transformWith(node, out); break; + case "ClassDecl"_id: transformClassDecl(node, out); break; + case "ForEach"_id: transformForEach(node, out); break; + case "For"_id: transformFor(node, out); break; + case "While"_id: transformWhile(node, out); break; + case "Do"_id: transformDo(node, out); break; + case "unary_exp"_id: transform_unary_exp(node, out); break; + case "TblComprehension"_id: transformTblComprehension(node, out); break; + case "TableLit"_id: transformTableLit(node, out); break; + case "Comprehension"_id: transformComprehension(node, out); break; + case "FunLit"_id: transformFunLit(node, out); break; + case "Num"_id: transformNum(node, out); break; + default: break; + } + }); + } + + void transformFunLit(ast_node* funLit, std::vector& out) { + std::vector temp; + bool isFatArrow = false; + bool hasArgsDef = false; + ast_node* body = nullptr; + pushScope(); + funLit->eachChild([&](ast_node* node) { + switch (node->getId()) { + case "FnArgsDef"_id: + hasArgsDef = true; + transformFnArgsDef(node, temp); + break; + case "fn_arrow"_id: + isFatArrow = toString(node) == "=>"sv; + break; + case "Body"_id: + transformBody(node, temp); + body = node; + break; + default: break; + } + }); + popScope(); + if (hasArgsDef) { + auto& args = temp[0]; + auto& initArgs = temp[1]; + auto& bodyCodes = temp[2]; + _buf << "function("sv << + (isFatArrow ? s("self"sv) + s(args.empty() ? ""sv : ", "sv) : Empty) << + args << ')' << nll(funLit) << + (initArgs.empty() ? Empty : initArgs) << + (body ? bodyCodes : Empty) << + indent() << "end"sv; + out.push_back(clearBuf()); + } else { + auto& bodyCodes = temp[0]; + out.push_back( + s("function()"sv) + nll(funLit) + + (body ? bodyCodes : Empty) + + indent() + s("end"sv) + ); } } - system("pause"); + + void transformBody(ast_node* body, std::vector& out) { + body->eachChild([&](ast_node* node) { + switch (node->getId()) { + case "Block"_id: transformBlock(node, out); break; + case "Statement"_id: transformStatement(node, out); break; + default: break; + } + }); + } + + void transformFnArgsDef(ast_node* argsDef, std::vector& out) { + argsDef->eachChild([&](ast_node* node) { + switch (node->getId()) { + case "FnArgDefList"_id: transformFnArgDefList(node, out); break; + case "outer_var_shadow"_id: transform_outer_var_shadow(node, out); break; + default: break; + } + }); + } + + void transform_outer_var_shadow(ast_node* shadow, std::vector& out) { + markVarShadowed(); + shadow->eachChild([&](ast_node* node) { + switch (node->getId()) { + case "NameList"_id: + node->eachChild([&](ast_node* child) { + if (child->getId() == "Name"_id) { + this->addToAllowList(toString(child)); + } + }); + break; + default: break; + } + }); + } + + void transformFnArgDefList(ast_node* argDefList, std::vector& out) { + std::vector> argItems; + const int Name = 0; + const int AssignSelf = 1; + const int DefaultVal = 2; + argDefList->eachChild([&](ast_node* node) { + switch (node->getId()) { + case "FnArgDef"_id: { + argItems.emplace_back(2); + auto& arg = argItems.back(); + node->eachChild([&](ast_node* child) { + switch (child->getId()) { + case "Name"_id: arg[Name] = toString(child); break; + case "SelfName"_id: + child->eachChild([&](ast_node* inner) { + switch (inner->getId()) { + case "self_class_name"_id: + arg[Name] = toString(inner->getChild(0)); + arg[AssignSelf] = s("self.__class."sv) + arg.front(); + break; + case "self_class"_id: + arg[Name] = "self.__class"sv; + break; + case "self_name"_id: + arg[Name] = toString(inner->getChild(0)); + arg[AssignSelf] = s("self."sv) + arg.front(); + break; + case "self"_id: + arg[Name] = "self"sv; + break; + } + }); + break; + case "Exp"_id: transformExp(child, arg); break; + default: break; + } + }); + break; + } + case "VarArg"_id: + argItems.emplace_back(2); + argItems.back()[Name] = "..."sv; + break; + default: break; + } + }); + std::string varNames; + for (const auto& item : argItems) { + if (varNames.empty()) { + varNames = item[Name]; + } else { + varNames.append(s(", "sv) + item[Name]); + } + forceAddToScope(item[Name]); + } + for (const auto& item : argItems) { + if (item.size() == 3 && !item[DefaultVal].empty()) { + _buf << indent() << "if "sv << item[Name] << " == nil then"sv << nll(argDefList) << + indent() << '\t' << item[Name] << " = "sv << item[DefaultVal] << nll(argDefList) << + indent() << "end"sv << nll(argDefList); + } + } + std::string initCodes = clearBuf(); + std::vector> assignSelfVars; + for (const auto& item : argItems) { + if (!item[AssignSelf].empty()) { + assignSelfVars.push_back({&item[AssignSelf], &item[Name]}); + } + } + auto sjoin = [](const decltype(assignSelfVars)& items, int index) { + std::string result; + for (auto it = items.begin(); it != items.end(); ++it) { + if (result.empty()) result = *((*it)[index]); + else result.append(s(", "sv) + *((*it)[index])); + } + return result; + }; + std::string sleft = sjoin(assignSelfVars, 0); + std::string sright = sjoin(assignSelfVars, 1); + if (!assignSelfVars.empty()) { + initCodes.append(sleft + s(" = "sv) + sright + nll(argDefList)); + } + out.push_back(varNames); + out.push_back(initCodes); + } + + void transformChain(ast_node* chain, std::vector& out) { + chain->eachChild([&](ast_node* node) { + switch (node->getId()) { + case "chain_call"_id: transform_chain_call(node, out); break; + case "chain_item"_id: transform_chain_item(node, out); break; + case "chain_dot_chain"_id: transform_chain_dot_chain(node, out); break; + case "ColonChain"_id: transformColonChain(node, out); break; + default: break; + } + }); + } + + void transform_chain_call(ast_node* chain_call, std::vector& out) { + std::vector temp; + chain_call->eachChild([&](ast_node* node) { + switch (node->getId()) { + case "Callable"_id: transformCallable(node, temp); break; + case "String"_id: transformString(node, temp); break; + case "ChainItems"_id: transformChainItems(node, temp); break; + default: break; + } + }); + out.push_back(join(temp)); + } + + void transformChainItems(ast_node* chainItems, std::vector& out) { + std::vector temp; + chainItems->eachChild([&](ast_node* node) { + switch (node->getId()) { + case "ChainItem"_id: transformChainItem(node, temp); break; + case "ColonChain"_id: transformColonChain(node, temp); break; + default: break; + } + }); + out.push_back(join(temp)); + } + + void transformChainItem(ast_node* chainItem, std::vector& out) { + chainItem->eachChild([&](ast_node* node) { + switch (node->getId()) { + case "Invoke"_id: transformInvoke(node, out); break; + case "DotChainItem"_id: + out.push_back(s("."sv) + toString(node->getChild(0))); + break; + case "Slice"_id: transformSlice(node, out); break; + case "Exp"_id: + transformExp(node, out); + out.back() = s("["sv) + out.back() + s("]"sv); + break; + default: break; + } + }); + } + + void transformInvoke(ast_node* invoke, std::vector& out) { + invoke->eachChild([&](ast_node* node) { + switch (node->getId()) { + case "FnArgs"_id: transformFnArgs(node, out); break; + case "SingleString"_id: transformSingleString(node, out); break; + case "DoubleString"_id: transformDoubleString(node, out); break; + case "LuaString"_id: transformLuaString(node, out); break; + default: break; + } + }); + } + + void transformFnArgs(ast_node* fnArgs, std::vector& out) { + std::vector temp; + fnArgs->eachChild([&](ast_node* node) { + switch (node->getId()) { + case "Exp"_id: transformExp(node, temp); break; + default: break; + } + }); + std::string args = join(temp, ", "); + out.push_back(args.empty() ? "()" : s("(") + args + ")"); + } + + void transformColonChain(ast_node* colonChain, std::vector& out) { + std::vector temp; + colonChain->eachChild([&](ast_node* node) { + switch (node->getId()) { + case "ColonChainItem"_id: + temp.push_back(s(":"sv) + toString(node->getChild(0))); + break; + case "invoke_chain"_id: transform_invoke_chain(node, temp); break; + default: break; + } + }); + out.push_back(join(temp)); + } + + void transform_invoke_chain(ast_node* invoke_chain, std::vector& out) { + std::vector temp; + invoke_chain->eachChild([&](ast_node* node) { + switch (node->getId()) { + case "Invoke"_id: transformInvoke(node, temp); break; + case "ChainItems"_id: transformChainItems(node, temp); break; + default: break; + } + }); + out.push_back(join(temp)); + } + + void transformUpdate(ast_node* node, std::vector& out) {noop(node, out);} + + void transformImport(ast_node* node, std::vector& out) {noopnl(node, out);} + void transformWhile(ast_node* node, std::vector& out) {noopnl(node, out);} + void transformWith(ast_node* node, std::vector& out) {noopnl(node, out);} + void transformIf(ast_node* node, std::vector& out) {noopnl(node, out);} + void transformFor(ast_node* node, std::vector& out) {noopnl(node, out);} + void transformForEach(ast_node* node, std::vector& out) {noopnl(node, out);} + void transformSwitch(ast_node* node, std::vector& out) {noopnl(node, out);} + void transformReturn(ast_node* node, std::vector& out) {noopnl(node, out);} + void transformTableBlock(ast_node* node, std::vector& out) {noopnl(node, out);} + void transformLocal(ast_node* node, std::vector& out) {noopnl(node, out);} + void transformExport(ast_node* node, std::vector& out) {noopnl(node, out);} + void transformBreakLoop(ast_node* node, std::vector& out) {noopnl(node, out);} + void transform_unless_line(ast_node* node, std::vector& out) {noop(node, out);} + void transformCompInner(ast_node* node, std::vector& out) {noop(node, out);} + void transform_simple_table(ast_node* node, std::vector& out) {noop(node, out);} + void transformString(ast_node* node, std::vector& out) {noop(node, out);} + void transformInvokeArgs(ast_node* node, std::vector& out) {noop(node, out);} + void transformName(ast_node* node, std::vector& out) {noop(node, out);} + void transformSelfName(ast_node* node, std::vector& out) {noop(node, out);} + void transform_const_value(ast_node* node, std::vector& out) {noop(node, out);} + void transformClassDecl(ast_node* node, std::vector& out) {noop(node, out);} + void transformDo(ast_node* node, std::vector& out) {noop(node, out);} + void transform_unary_exp(ast_node* node, std::vector& out) {noop(node, out);} + void transformTblComprehension(ast_node* node, std::vector& out) {noop(node, out);} + void transformTableLit(ast_node* node, std::vector& out) {noop(node, out);} + void transformComprehension(ast_node* node, std::vector& out) {noop(node, out);} + void transformNum(ast_node* node, std::vector& out) {noop(node, out);} + void transformVarArg(ast_node* node, std::vector& out) {noop(node, out);} + void transformBinaryOperator(ast_node* node, std::vector& out) {noop(node, out);} + void transform_chain_item(ast_node* node, std::vector& out) {noop(node, out);} + void transform_chain_dot_chain(ast_node* node, std::vector& out) {noop(node, out);} + void transformSlice(ast_node* node, std::vector& out) {noop(node, out);} + void transformSingleString(ast_node* node, std::vector& out) {noop(node, out);} + void transformDoubleString(ast_node* node, std::vector& out) {noop(node, out);} + void transformLuaString(ast_node* node, std::vector& out) {noop(node, out);} +}; + +const std::string MoonCompliler::Empty; + +int main() +{ + std::string s = R"TestCodesHere(a = 998 +f, d = (-> + joop = 2302 + 567 + + (hi, a, b = Vec2(100,200), c, d, ... using nil) -> + d = "中文" + hi = 1021 + + a,b,c,d = 1,2,3,4 + + hello[232], (5+5)[121], hello, x[99] = 100, 200, 300 + + joop = 12), 123 if true else print("a",1,2)\abc(998).x + +a, b = if hello + "hello" +else + "nothing", "yeah" + + +a, b = if hello + if yeah then "one", "two" else "mmhh" +else + print "the other" + "nothing", "yeah")TestCodesHere"; + + MoonCompliler{}.complile(s); + return 0; } diff --git a/MoonParser/moon_ast.h b/MoonParser/moon_ast.h index 4511b1b..9eab2f9 100644 --- a/MoonParser/moon_ast.h +++ b/MoonParser/moon_ast.h @@ -2,7 +2,19 @@ #include "moon_parser.h" -input& trim(input& s); +template +std::basic_string& trim(std::basic_string& s) +{ + s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](T ch) + { + return !std::isspace(ch); + })); + s.erase(std::find_if(s.rbegin(), s.rend(), [](T ch) + { + return !std::isspace(ch); + }).base(), s.end()); + return s; +} class AstLeaf : public ast_node { @@ -12,137 +24,139 @@ private: input _value; }; -#define AST_LEAF(type) \ +#define AST_LEAF(type, id) \ extern rule type; \ class type##_t : public AstLeaf \ { \ 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) \ +#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_END(type) \ }; -AST_LEAF(Num) +AST_LEAF(Num, "Num"_id) AST_END(Num) -AST_LEAF(_Name) +AST_LEAF(_Name, "_Name"_id) AST_END(_Name) -AST_NODE(Name) +AST_NODE(Name, "Name"_id) ast_ptr<_Name_t> name; AST_END(Name) -AST_LEAF(self) +AST_LEAF(self, "self"_id) AST_END(self) -AST_NODE(self_name) +AST_NODE(self_name, "self_name"_id) ast_ptr<_Name_t> name; AST_END(self_name) -AST_LEAF(self_class) +AST_LEAF(self_class, "self_class"_id) AST_END(self_class) -AST_NODE(self_class_name) +AST_NODE(self_class_name, "self_class_name"_id) ast_ptr<_Name_t> name; AST_END(self_class_name) -AST_NODE(SelfName) +AST_NODE(SelfName, "SelfName"_id) ast_ptr name; // self_class_name_t | self_class_t | self_name_t | self_t AST_END(SelfName) -AST_NODE(KeyName) +AST_NODE(KeyName, "KeyName"_id) ast_ptr name; // SelfName_t | _Name_t AST_END(KeyName) -AST_LEAF(VarArg) +AST_LEAF(VarArg, "VarArg"_id) AST_END(VarArg) -AST_LEAF(local_flag) +AST_LEAF(local_flag, "local_flag"_id) AST_END(local_flag) -AST_LEAF(Seperator) +AST_LEAF(Seperator, "Seperator"_id) AST_END(Seperator) -AST_NODE(NameList) +AST_NODE(NameList, "NameList"_id) ast_ptr sep; ast_list names; AST_END(NameList) -AST_NODE(Local) +AST_NODE(Local, "Local"_id) ast_ptr name; // local_flag_t | NameList_t AST_END(Local) -AST_NODE(colon_import_name) +AST_NODE(colon_import_name, "colon_import_name"_id) ast_ptr name; AST_END(colon_import_name) class Exp_t; -AST_NODE(ImportName) +AST_NODE(ImportName, "ImportName"_id) ast_ptr name; // colon_import_name_t | Name_t AST_END(ImportName) -AST_NODE(Import) +AST_NODE(Import, "Import"_id) ast_ptr sep; ast_list names; ast_ptr exp; AST_END(Import) -AST_NODE(ExpListLow) +AST_NODE(ExpListLow, "ExpListLow"_id) ast_ptr sep; ast_list exprs; AST_END(ExpListLow) -AST_NODE(ExpList) +AST_NODE(ExpList, "ExpList"_id) ast_ptr sep; ast_list exprs; AST_END(ExpList) -AST_NODE(Return) +AST_NODE(Return, "Return"_id) ast_ptr valueList; AST_END(Return) class Assign_t; class Body_t; -AST_NODE(With) +AST_NODE(With, "With"_id) ast_ptr valueList; ast_ptr assigns; ast_ptr body; AST_END(With) -AST_NODE(SwitchCase) +AST_NODE(SwitchCase, "SwitchCase"_id) ast_ptr valueList; ast_ptr body; AST_END(SwitchCase) -AST_NODE(Switch) +AST_NODE(Switch, "Switch"_id) ast_ptr target; ast_ptr sep; ast_list branches; ast_ptr lastBranch; AST_END(Switch) -AST_NODE(IfCond) +AST_NODE(IfCond, "IfCond"_id) ast_ptr condition; ast_ptr assign; AST_END(IfCond) -AST_NODE(IfElseIf) +AST_NODE(IfElseIf, "IfElseIf"_id) ast_ptr condition; ast_ptr body; AST_END(IfElseIf) -AST_NODE(If) +AST_NODE(If, "If"_id) ast_ptr firstCondition; ast_ptr firstBody; ast_ptr sep; @@ -150,7 +164,7 @@ AST_NODE(If) ast_ptr lastBranch; AST_END(If) -AST_NODE(Unless) +AST_NODE(Unless, "Unless"_id) ast_ptr firstCondition; ast_ptr firstBody; ast_ptr sep; @@ -158,16 +172,16 @@ AST_NODE(Unless) ast_ptr lastBranch; AST_END(Unless) -AST_NODE(While) +AST_NODE(While, "While"_id) ast_ptr condition; ast_ptr body; AST_END(While) -AST_NODE(for_step_value) +AST_NODE(for_step_value, "for_step_value"_id) ast_ptr value; AST_END(for_step_value) -AST_NODE(For) +AST_NODE(For, "For"_id) ast_ptr varName; ast_ptr startValue; ast_ptr stopValue; @@ -177,54 +191,54 @@ AST_END(For) class AssignableNameList_t; -AST_NODE(ForEach) +AST_NODE(ForEach, "ForEach"_id) ast_ptr nameList; ast_ptr loopValue; // Exp_t | ExpList_t ast_ptr body; AST_END(ForEach) -AST_NODE(Do) +AST_NODE(Do, "Do"_id) ast_ptr body; AST_END(Do) class CompInner_t; -AST_NODE(Comprehension) +AST_NODE(Comprehension, "Comprehension"_id) ast_ptr value; ast_ptr forLoop; AST_END(Comprehension) -AST_NODE(comp_value) +AST_NODE(comp_value, "comp_value"_id) ast_ptr value; AST_END(comp_value) -AST_NODE(TblComprehension) +AST_NODE(TblComprehension, "TblComprehension"_id) ast_ptr key; ast_ptr value; ast_ptr forLoop; AST_END(TblComprehension) -AST_NODE(star_exp) +AST_NODE(star_exp, "star_exp"_id) ast_ptr value; AST_END(star_exp) -AST_NODE(CompForEach) +AST_NODE(CompForEach, "CompForEach"_id) ast_ptr nameList; ast_ptr loopValue; // star_exp_t | Exp_t AST_END(CompForEach) -AST_NODE(CompFor) +AST_NODE(CompFor, "CompFor"_id) ast_ptr varName; ast_ptr startValue; ast_ptr stopValue; ast_ptr stepValue; AST_END(CompFor) -AST_NODE(CompClause) +AST_NODE(CompClause, "CompClause"_id) ast_ptr nestExp; // CompFor_t | CompForEach_t | Exp_t AST_END(CompClause) -AST_NODE(CompInner) +AST_NODE(CompInner, "CompInner"_id) ast_ptr compFor; // CompFor_t | CompForEach_t ast_ptr sep; ast_list clauses; @@ -232,60 +246,60 @@ AST_END(CompInner) class TableBlock_t; -AST_NODE(Assign) +AST_NODE(Assign, "Assign"_id) ast_ptr value; // With_t | If_t | Switch_t | TableBlock_t | ExpListLow_t AST_END(Assign) -AST_LEAF(update_op) +AST_LEAF(update_op, "update_op"_id) AST_END(update_op) -AST_NODE(Update) +AST_NODE(Update, "Update"_id) ast_ptr op; ast_ptr value; AST_END(Update) -AST_LEAF(BinaryOperator) +AST_LEAF(BinaryOperator, "BinaryOperator"_id) AST_END(BinaryOperator) class Chain_t; -AST_NODE(Assignable) +AST_NODE(Assignable, "Assignable"_id) ast_ptr item; // Chain_t | Name_t | SelfName_t AST_END(Assignable) class Value_t; -AST_NODE(exp_op_value) +AST_NODE(exp_op_value, "exp_op_value"_id) ast_ptr op; ast_ptr value; AST_END(exp_op_value) -AST_NODE(Exp) +AST_NODE(Exp, "Exp"_id) ast_ptr value; ast_list opValues; AST_END(Exp) -AST_NODE(Callable) +AST_NODE(Callable, "Callable"_id) ast_ptr item; // Name_t | SelfName_t | VarArg_t | Parens_t AST_END(Callable) class InvokeArgs_t; -AST_NODE(ChainValue) +AST_NODE(ChainValue, "ChainValue"_id) ast_ptr caller; // Chain_t | Callable_t ast_ptr arguments; AST_END(ChainValue) class KeyValue_t; -AST_NODE(simple_table) +AST_NODE(simple_table, "simple_table"_id) ast_ptr sep; ast_list pairs; AST_END(simple_table) class String_t; -AST_NODE(SimpleValue) +AST_NODE(SimpleValue, "SimpleValue"_id) ast_ptr value; /* const_value_t | If_t | Unless_t | Switch_t | With_t | ClassDecl_t | ForEach_t | For_t | While_t | Do_t | @@ -294,65 +308,65 @@ AST_NODE(SimpleValue) */ AST_END(SimpleValue) -AST_NODE(Chain) +AST_NODE(Chain, "Chain"_id) ast_ptr item; // chain_call_t | chain_item_t | chain_dot_chain_t | ColonChain_t AST_END(Chain) -AST_NODE(Value) +AST_NODE(Value, "Value"_id) ast_ptr item; // SimpleValue_t | simple_table_t | ChainValue_t | String_t AST_END(Value) -AST_LEAF(LuaString) +AST_LEAF(LuaString, "LuaString"_id) AST_END(LuaString) -AST_LEAF(SingleString) +AST_LEAF(SingleString, "SingleString"_id) AST_END(SingleString) -AST_LEAF(double_string_inner) +AST_LEAF(double_string_inner, "double_string_inner"_id) AST_END(double_string_inner) -AST_NODE(double_string_content) +AST_NODE(double_string_content, "double_string_content"_id) ast_ptr content; // double_string_inner_t | Exp_t AST_END(double_string_content) -AST_NODE(DoubleString) +AST_NODE(DoubleString, "DoubleString"_id) ast_ptr sep; ast_list segments; AST_END(DoubleString) -AST_NODE(String) +AST_NODE(String, "String"_id) ast_ptr str; // DoubleString_t | SingleString_t | LuaString_t AST_END(String) -AST_NODE(Parens) +AST_NODE(Parens, "Parens"_id) ast_ptr expr; AST_END(Parens) -AST_NODE(FnArgs) +AST_NODE(FnArgs, "FnArgs"_id) ast_ptr sep; ast_list args; AST_END(FnArgs) class ChainItems_t; -AST_NODE(chain_call) +AST_NODE(chain_call, "chain_call"_id) ast_ptr caller; // Callable_t | String_t ast_ptr chain; AST_END(chain_call) -AST_NODE(chain_item) +AST_NODE(chain_item, "chain_item"_id) ast_ptr chain; AST_END(chain_item) -AST_NODE(DotChainItem) +AST_NODE(DotChainItem, "DotChainItem"_id) ast_ptr<_Name_t> name; AST_END(DotChainItem) -AST_NODE(ColonChainItem) +AST_NODE(ColonChainItem, "ColonChainItem"_id) ast_ptr<_Name_t> name; AST_END(ColonChainItem) -AST_NODE(chain_dot_chain) +AST_NODE(chain_dot_chain, "chain_dot_chain"_id) ast_ptr caller; ast_ptr chain; AST_END(chain_dot_chain) @@ -361,183 +375,183 @@ class ColonChain_t; class Invoke_t; class Slice_t; -AST_NODE(ChainItem) +AST_NODE(ChainItem, "ChainItem"_id) ast_ptr item; // Invoke_t | DotChainItem_t | Slice_t | [Exp_t] AST_END(ChainItem) -AST_NODE(ChainItems) +AST_NODE(ChainItems, "ChainItems"_id) ast_ptr sep; ast_list simpleChain; ast_ptr colonChain; AST_END(ChainItems) -AST_NODE(invoke_chain) +AST_NODE(invoke_chain, "invoke_chain"_id) ast_ptr invoke; ast_ptr chain; AST_END(invoke_chain) -AST_NODE(ColonChain) +AST_NODE(ColonChain, "ColonChain"_id) ast_ptr colonChain; ast_ptr invokeChain; AST_END(ColonChain) -AST_LEAF(default_value) +AST_LEAF(default_value, "default_value"_id) AST_END(default_value) -AST_NODE(Slice) +AST_NODE(Slice, "Slice"_id) ast_ptr startValue; // Exp_t | default_value_t ast_ptr stopValue; // Exp_t | default_value_t ast_ptr stepValue; // Exp_t | default_value_t AST_END(Slice) -AST_NODE(Invoke) +AST_NODE(Invoke, "Invoke"_id) ast_ptr argument; // FnArgs_t | SingleString_t | DoubleString_t | LuaString_t AST_END(Invoke) class KeyValue_t; -AST_NODE(TableValue) +AST_NODE(TableValue, "TableValue"_id) ast_ptr value; // KeyValue_t | Exp_t AST_END(TableValue) -AST_NODE(TableLit) +AST_NODE(TableLit, "TableLit"_id) ast_ptr sep; ast_list values; AST_END(TableLit) -AST_NODE(TableBlock) +AST_NODE(TableBlock, "TableBlock"_id) ast_ptr sep; ast_list values; AST_END(TableBlock) -AST_NODE(class_member_list) +AST_NODE(class_member_list, "class_member_list"_id) ast_ptr sep; ast_list values; AST_END(class_member_list) -AST_NODE(ClassLine) +AST_NODE(ClassLine, "ClassLine"_id) ast_ptr content; // class_member_list_t | Statement_t | Exp_t AST_END(ClassLine) -AST_NODE(ClassBlock) +AST_NODE(ClassBlock, "ClassBlock"_id) ast_ptr sep; ast_list lines; AST_END(ClassBlock) -AST_NODE(ClassDecl) +AST_NODE(ClassDecl, "ClassDecl"_id) ast_ptr name; ast_ptr extend; ast_ptr body; AST_END(ClassDecl) -AST_NODE(export_values) +AST_NODE(export_values, "export_values"_id) ast_ptr nameList; ast_ptr valueList; AST_END(export_values) -AST_LEAF(export_op) +AST_LEAF(export_op, "export_op"_id) AST_END(export_op) -AST_NODE(Export) +AST_NODE(Export, "Export"_id) ast_ptr item; // ClassDecl_t | export_op_t | export_values_t AST_END(Export) -AST_NODE(variable_pair) +AST_NODE(variable_pair, "variable_pair"_id) ast_ptr name; AST_END(variable_pair) -AST_NODE(normal_pair) +AST_NODE(normal_pair, "normal_pair"_id) ast_ptr key; // KeyName_t | [Exp_t] | DoubleString_t | SingleString_t ast_ptr value; // Exp_t | TableBlock_t AST_END(normal_pair) -AST_NODE(KeyValue) +AST_NODE(KeyValue, "KeyValue"_id) ast_ptr item; // variable_pair_t | normal_pair_t AST_END(KeyValue) -AST_NODE(FnArgDef) +AST_NODE(FnArgDef, "FnArgDef"_id) ast_ptr name; // Name_t | SelfName_t ast_ptr defaultValue; AST_END(FnArgDef) -AST_NODE(FnArgDefList) +AST_NODE(FnArgDefList, "FnArgDefList"_id) ast_ptr sep; ast_list definitions; ast_ptr varArg; AST_END(FnArgDefList) -AST_NODE(outer_var_shadow) +AST_NODE(outer_var_shadow, "outer_var_shadow"_id) ast_ptr varList; AST_END(outer_var_shadow) -AST_NODE(FnArgsDef) +AST_NODE(FnArgsDef, "FnArgsDef"_id) ast_ptr defList; ast_ptr shadowOption; AST_END(FnArgsDef) -AST_LEAF(fn_arrow) +AST_LEAF(fn_arrow, "fn_arrow"_id) AST_END(fn_arrow) -AST_NODE(FunLit) +AST_NODE(FunLit, "FunLit"_id) ast_ptr argsDef; ast_ptr arrow; ast_ptr body; AST_END(FunLit) -AST_NODE(NameOrDestructure) +AST_NODE(NameOrDestructure, "NameOrDestructure"_id) ast_ptr item; // Name_t | TableLit_t AST_END(NameOrDestructure) -AST_NODE(AssignableNameList) +AST_NODE(AssignableNameList, "AssignableNameList"_id) ast_ptr sep; ast_list items; AST_END(AssignableNameList) -AST_NODE(ArgBlock) +AST_NODE(ArgBlock, "ArgBlock"_id) ast_ptr sep; ast_list arguments; AST_END(ArgBlock) -AST_NODE(invoke_args_with_table) +AST_NODE(invoke_args_with_table, "invoke_args_with_table"_id) ast_ptr argBlock; ast_ptr tableBlock; AST_END(invoke_args_with_table) -AST_NODE(InvokeArgs) +AST_NODE(InvokeArgs, "InvokeArgs"_id) ast_ptr argsList; ast_ptr argsTableBlock; ast_ptr tableBlock; AST_END(InvokeArgs) -AST_LEAF(const_value) +AST_LEAF(const_value, "const_value"_id) AST_END(const_value) -AST_NODE(unary_exp) +AST_NODE(unary_exp, "unary_exp"_id) ast_ptr item; AST_END(unary_exp) -AST_NODE(Assignment) +AST_NODE(Assignment, "Assignment"_id) ast_ptr assignable; ast_ptr target; // Update_t | Assign_t AST_END(Assignment) -AST_NODE(if_else_line) +AST_NODE(if_else_line, "if_else_line"_id) ast_ptr condition; ast_ptr elseExpr; // Exp_t | default_value_t AST_END(if_else_line) -AST_NODE(unless_line) +AST_NODE(unless_line, "unless_line"_id) ast_ptr condition; AST_END(unless_line) -AST_NODE(statement_appendix) +AST_NODE(statement_appendix, "statement_appendix"_id) ast_ptr item; // if_else_line_t | unless_line_t | CompInner_t AST_END(statement_appendix) -AST_LEAF(BreakLoop) +AST_LEAF(BreakLoop, "BreakLoop"_id) AST_END(BreakLoop) -AST_NODE(Statement) +AST_NODE(Statement, "Statement"_id) ast_ptr content; /* Import_t | While_t | With_t | For_t | ForEach_t | Switch_t | Return_t | Local_t | Export_t | BreakLoop_t | @@ -548,19 +562,19 @@ AST_END(Statement) class Block_t; -AST_NODE(Body) +AST_NODE(Body, "Body"_id) ast_ptr content; // Block | Statement AST_END(Body) -AST_NODE(Line) +AST_NODE(Line, "Line"_id) ast_ptr statment; AST_END(Line) -AST_NODE(Block) +AST_NODE(Block, "Block"_id) ast_ptr sep; ast_list lines; AST_END(Block) -AST_NODE(BlockEnd) +AST_NODE(BlockEnd, "BlockEnd"_id) ast_ptr block; AST_END(BlockEnd) diff --git a/MoonParser/moon_parser.h b/MoonParser/moon_parser.h index 0c3f427..bf618aa 100644 --- a/MoonParser/moon_parser.h +++ b/MoonParser/moon_parser.h @@ -26,6 +26,6 @@ struct State "local", "not", "then", "return", "from", "extends", "for", "do", "or", "export", "class", "in", "unless", "when", "elseif", - "switch", "break", "if", "with", "import" + "switch", "break", "if", "with", "import", "true", "false", "nil" }; }; diff --git a/MoonParser/parser.hpp b/MoonParser/parser.hpp index 66d6067..cbabf06 100644 --- a/MoonParser/parser.hpp +++ b/MoonParser/parser.hpp @@ -16,6 +16,19 @@ #include #include +// const str hash helper functions +inline constexpr std::size_t hash(char const* input) +{ + return *input ? *input + 33ull * hash(input + 1) : 5381; +} +inline std::size_t hash(const char* input, int size, int index) +{ + return index < size ? input[index] + 33ull * hash(input, size, index + 1) : 5381; +} +inline std::size_t constexpr operator"" _id(const char* s, size_t) +{ + return hash(s); +} ///type of the parser's input. typedef std::basic_string input; -- cgit v1.2.3-55-g6feb