From c62d9eb35a310e7663234526ce4b9fe3519ca7cf Mon Sep 17 00:00:00 2001 From: Li Jin Date: Thu, 30 Jan 2020 16:06:32 +0800 Subject: Separate MoonParser from MoonCompiler, make moonc compile multiple file in threads. --- spec/inputs/backcall.moon | 10 +- src/MoonP/ast.cpp | 2 +- src/MoonP/ast.hpp | 24 +- src/MoonP/moon_ast.cpp | 120 ------ src/MoonP/moon_ast.h | 5 +- src/MoonP/moon_compiler.cpp | 401 +++++++----------- src/MoonP/moon_parser.cpp | 972 +++++++++++++++++++++++--------------------- src/MoonP/moon_parser.h | 263 +++++++++++- src/MoonP/parser.cpp | 50 +-- src/MoonP/parser.hpp | 22 +- src/moonc.cpp | 155 +++---- 11 files changed, 1043 insertions(+), 981 deletions(-) delete mode 100644 src/MoonP/moon_ast.cpp diff --git a/spec/inputs/backcall.moon b/spec/inputs/backcall.moon index 355089a..7702059 100644 --- a/spec/inputs/backcall.moon +++ b/spec/inputs/backcall.moon @@ -31,17 +31,19 @@ f = -> 998 |> func0("abc", 233) |> func1 |> func2 do - (data) <- http?.get "ajaxtest" + (data)<- http?.get "ajaxtest" body[".result"]\html data - (processed) <- http.post "ajaxprocess", data + (processed)<- http.post "ajaxprocess", data body[".result"]\append processed <- setTimeout 1000 print "done" do <- syncStatus - (err,data="nil") <- loadAsync "file.moon" - print err if err + (err,data="nil")<- loadAsync "file.moon" + if err + print err + return (codes) <- compileAsync data func = loadstring codes func! diff --git a/src/MoonP/ast.cpp b/src/MoonP/ast.cpp index cda2339..7cdefba 100644 --- a/src/MoonP/ast.cpp +++ b/src/MoonP/ast.cpp @@ -115,7 +115,7 @@ bool ast_container::visitChild(const std::function& func) { @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_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) { diff --git a/src/MoonP/ast.hpp b/src/MoonP/ast.hpp index 0b5ffca..38141e2 100644 --- a/src/MoonP/ast.hpp +++ b/src/MoonP/ast.hpp @@ -522,7 +522,6 @@ public: ast(rule& r) { r.set_parse_proc(&_parse_proc); } - private: //parse proc static void _parse_proc(const pos& b, const pos& e, void* d) { @@ -544,28 +543,7 @@ private: @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; -} +ast_node* parse(input& i, rule& g, error_list& el, void* ud); } //namespace parserlib diff --git a/src/MoonP/moon_ast.cpp b/src/MoonP/moon_ast.cpp deleted file mode 100644 index f14fa74..0000000 --- a/src/MoonP/moon_ast.cpp +++ /dev/null @@ -1,120 +0,0 @@ -/* Copyright (c) 2020 Jin Li, http://www.luvfight.me - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "MoonP/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_literal_inner) -AST_IMPL(ImportLiteral) -AST_IMPL(ImportFrom) -AST_IMPL(ImportAs) -AST_IMPL(Import) -AST_IMPL(Backcall) -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(BackcallOperator) -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(existential_op) -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/src/MoonP/moon_ast.h b/src/MoonP/moon_ast.h index 6969688..86f5ef3 100644 --- a/src/MoonP/moon_ast.h +++ b/src/MoonP/moon_ast.h @@ -8,12 +8,12 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI #pragma once -#include "MoonP/moon_parser.h" +#include "MoonP/ast.hpp" +using namespace parserlib; namespace MoonP { #define AST_LEAF(type, id) \ -extern rule type; \ class type##_t : public ast_node \ { \ public: \ @@ -21,7 +21,6 @@ public: \ virtual size_t getId() const override { return id; } \ #define AST_NODE(type, id) \ -extern rule type; \ class type##_t : public ast_container \ { \ public: \ diff --git a/src/MoonP/moon_compiler.cpp b/src/MoonP/moon_compiler.cpp index caa7aaf..ceaff96 100644 --- a/src/MoonP/moon_compiler.cpp +++ b/src/MoonP/moon_compiler.cpp @@ -13,11 +13,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI #include #include #include -#include -#include -using namespace std::string_view_literals; -#include "MoonP/parser.hpp" -#include "MoonP/moon_ast.h" +#include "MoonP/moon_parser.h" #include "MoonP/moon_compiler.h" namespace MoonP { @@ -40,25 +36,12 @@ class MoonCompiler { public: std::pair compile(const std::string& codes, const MoonConfig& config) { _config = config; - try { - _input = _converter.from_bytes(codes); - } catch (const std::range_error&) { - return {Empty, "Invalid text encoding."}; - } - 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) { + _info = _parser.parse(codes); + if (_info.node) { try { str_list out; pushScope(); - transformBlock(root->block, out, config.implicitReturnRoot); + transformBlock(_info.node.to()->block, out, config.implicitReturnRoot); popScope(); return {std::move(out.back()), Empty}; } catch (const std::logic_error& error) { @@ -66,14 +49,8 @@ public: 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; + return {Empty, _info.error}; } } @@ -94,14 +71,13 @@ public: _joinBuf.str(""); _joinBuf.clear(); _globals.clear(); - _input.clear(); } private: MoonConfig _config; + MoonParser _parser; + ParseInfo _info; int _indentOffset = 0; - Converter _converter; - input _input; - std::list _codeCache; + std::list> _codeCache; std::stack _withVars; std::stack _continueVars; std::unordered_map> _globals; @@ -329,14 +305,6 @@ private: 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) const { Exp_t* exp = nullptr; switch (item->getId()) { @@ -400,26 +368,15 @@ private: } 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) { + ast_ptr toAst(std::string_view codes, ast_node* parent) { + auto res = _parser.parse(s(codes)); + res.node->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; + _codeCache.push_back(std::move(res.input)); + return ast_ptr(res.node.template to()); } bool isChainValueCall(ChainValue_t* chainValue) const { @@ -547,7 +504,7 @@ private: 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)); + throw std::logic_error(_info.errorMessage("Left hand expression is not assignable."sv, exp)); } } } @@ -567,40 +524,6 @@ private: return backcall; } - std::string debugInfo(std::string_view msg, const input_range* loc) const { - 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 = std::max(0, oldCol - 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) { @@ -761,7 +684,7 @@ private: break; } } - throw std::logic_error(debugInfo("Expression list must appear at the end of body block."sv, expList)); + throw std::logic_error(_info.errorMessage("Expression list must appear at the end of body block."sv, expList)); } break; } @@ -800,7 +723,7 @@ private: BREAK_IF(!callable); std::string name; if (auto var = callable->item.as()) { - name = toString(var); + name = _parser.toString(var); } else if (auto self = callable->item.as()) { if (self->name.is()) name = "self"sv; } @@ -811,7 +734,7 @@ private: BLOCK_END } } else { - throw std::logic_error(debugInfo("Left hand expression is not assignable."sv, exp)); + throw std::logic_error(_info.errorMessage("Left hand expression is not assignable."sv, exp)); } } return preDefs; @@ -829,7 +752,7 @@ private: BREAK_IF(!callable); std::string name; if (auto var = callable->item.as()) { - name = toString(var); + name = _parser.toString(var); } else if (auto self = callable->item.as()) { if (self->name.is()) name = "self"sv; } @@ -840,7 +763,7 @@ private: BLOCK_END } } else { - throw std::logic_error(debugInfo("Left hand expression is not assignable."sv, exp)); + throw std::logic_error(_info.errorMessage("Left hand expression is not assignable."sv, exp)); } } return preDefs; @@ -1071,7 +994,7 @@ private: _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)) { + } else if (_parser.match(destruct.value)) { str_list defs, names, values; for (const auto& item : destruct.items) { if (item.isVariable && addToScope(item.name)) { @@ -1134,7 +1057,7 @@ private: 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)); + if (!item) throw std::logic_error(_info.errorMessage("Invalid destructure value."sv, node)); auto tbA = item->getByPath(); if (tbA) { tableItems = &tbA->values.objects(); @@ -1152,7 +1075,7 @@ private: case "Exp"_id: { ++index; if (!isAssignable(static_cast(pair))) { - throw std::logic_error(debugInfo("Can't destructure value."sv, pair)); + throw std::logic_error(_info.errorMessage("Can't destructure value."sv, pair)); } auto value = singleValueFrom(pair); auto item = value->item.get(); @@ -1185,8 +1108,8 @@ private: } case "variable_pair"_id: { auto vp = static_cast(pair); - auto name = toString(vp->name); - if (State::keywords.find(name) != State::keywords.end()) { + auto name = _parser.toString(vp->name); + if (Keywords.find(name) != Keywords.end()) { pairs.push_back({true, name, s("[\""sv) + name + s("\"]"sv)}); } else { pairs.push_back({true, name, s("."sv) + name}); @@ -1196,16 +1119,16 @@ private: 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 (!key) throw std::logic_error(_info.errorMessage("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)); + if (!isAssignable(exp)) throw std::logic_error(_info.errorMessage("Can't destructure value."sv, exp)); auto item = singleValueFrom(exp)->item.get(); if (ast_cast(item) || item->getByPath()) { auto subPairs = destructFromExp(exp); - auto name = toString(key); + auto name = _parser.toString(key); for (auto& p : subPairs) { - if (State::keywords.find(name) != State::keywords.end()) { + if (Keywords.find(name) != Keywords.end()) { pairs.push_back({p.isVariable, p.name, s("[\""sv) + name + s("\"]"sv) + p.structure}); } else { @@ -1224,8 +1147,8 @@ private: varName = std::move(temp.back()); } _config.lintGlobalVariable = lintGlobal; - auto name = toString(key); - if (State::keywords.find(name) != State::keywords.end()) { + auto name = _parser.toString(key); + if (Keywords.find(name) != Keywords.end()) { pairs.push_back({ isVariable, varName, @@ -1245,7 +1168,7 @@ private: auto subPairs = destructFromExp(pair); for (auto& p : subPairs) { pairs.push_back({p.isVariable, p.name, - s("."sv) + toString(key) + p.structure}); + s("."sv) + _parser.toString(key) + p.structure}); } } break; @@ -1265,12 +1188,12 @@ private: size_t size = std::max(exprs.size(),values.size()); ast_ptr var; if (exprs.size() < size) { - var = toAst("_"sv, Exp, x); + var = toAst("_"sv, x); while (exprs.size() < size) exprs.emplace_back(var); } ast_ptr nullNode; if (values.size() < size) { - nullNode = toAst("nil"sv, Exp, x); + nullNode = toAst("nil"sv, x); while (values.size() < size) values.emplace_back(nullNode); } using iter = node_container::iterator; @@ -1319,11 +1242,11 @@ private: auto action = assignment->action.get(); switch (action->getId()) { case "Update"_id: { - if (expList->exprs.size() > 1) throw std::logic_error(debugInfo("Can not apply update to multiple values."sv, expList)); + if (expList->exprs.size() > 1) throw std::logic_error(_info.errorMessage("Can not apply update to multiple values."sv, expList)); 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 (!leftValue) throw std::logic_error(_info.errorMessage("Left hand expression is not assignable."sv, leftExp)); if (auto chain = leftValue->getByPath()) { auto tmpChain = x->new_ptr(); for (auto item : chain->items.objects()) { @@ -1335,12 +1258,12 @@ private: BREAK_IF(!var.empty()); auto upVar = getUnusedName("_update_"sv); auto assignment = x->new_ptr(); - assignment->expList.set(toAst(upVar, ExpList, x)); + assignment->expList.set(toAst(upVar, 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)); + tmpChain->items.push_back(toAst(upVar, x)); itemAdded = true; BLOCK_END if (!itemAdded) tmpChain->items.push_back(item); @@ -1358,7 +1281,7 @@ private: right = s("("sv) + right + s(")"sv); } _buf << join(temp) << indent() << left << " = "sv << left << - " "sv << toString(update->op) << " "sv << right << nll(assignment); + " "sv << _parser.toString(update->op) << " "sv << right << nll(assignment); out.push_back(clearBuf()); break; } @@ -1372,7 +1295,7 @@ private: switch (callable->item->getId()) { case "Variable"_id: for (const auto& def : defs) { - if (def == toString(callable->item)) { + if (def == _parser.toString(callable->item)) { return traversal::Stop; } } @@ -1510,7 +1433,7 @@ private: temp.push_back(indent() + s("do"sv) + nll(assign)); pushScope(); } - auto expList = toAst(desVar, ExpList, x); + auto expList = toAst(desVar, x); auto assignment = x->new_ptr(); assignment->expList.set(expList); assignment->action.set(assign); @@ -1520,7 +1443,7 @@ private: auto expList = x->new_ptr(); expList->exprs.push_back(exp); auto assignOne = x->new_ptr(); - auto valExp = toAst(desVar, Exp, x); + auto valExp = toAst(desVar, x); assignOne->values.push_back(valExp); auto assignment = x->new_ptr(); assignment->expList.set(expList); @@ -1668,7 +1591,7 @@ private: } return; } else { - throw std::logic_error(debugInfo("Backcall operator must be followed by chain value."sv, opValue->value)); + throw std::logic_error(_info.errorMessage("Backcall operator must be followed by chain value."sv, opValue->value)); } } } @@ -1762,7 +1685,7 @@ private: void transformFunLit(FunLit_t* funLit, str_list& out) { str_list temp; - bool isFatArrow = toString(funLit->arrow) == "=>"sv; + bool isFatArrow = _parser.toString(funLit->arrow) == "=>"sv; pushScope(); if (isFatArrow) { forceAddToScope(s("self"sv)); @@ -1839,7 +1762,7 @@ private: body->content.set(block); auto funLit = x->new_ptr(); funLit->argsDef.set(backcall->argsDef); - funLit->arrow.set(toAst("->"sv, fn_arrow, x)); + funLit->arrow.set(toAst("->"sv, x)); funLit->body.set(body); auto simpleValue = x->new_ptr(); simpleValue->value.set(funLit); @@ -1878,7 +1801,7 @@ private: } if (auto local = stmt->content.as()) { if (auto flag = local->name.as()) { - LocalMode newMode = toString(flag) == "*"sv ? LocalMode::Any : LocalMode::Capital; + LocalMode newMode = _parser.toString(flag) == "*"sv ? LocalMode::Any : LocalMode::Capital; if (int(newMode) > int(mode)) { mode = newMode; } @@ -1891,7 +1814,7 @@ private: } else { auto names = local->name.to(); for (auto name : names->names.objects()) { - local->forceDecls.push_back(toString(name)); + local->forceDecls.push_back(_parser.toString(name)); } } } else if (mode != LocalMode::None) { @@ -1932,7 +1855,7 @@ private: } if (classDecl) { if (auto variable = classDecl->name->item.as()) { - auto className = toString(variable); + auto className = _parser.toString(variable); if (!className.empty()) { if (std::isupper(className[0]) && capital) { capital->decls.push_back(className); @@ -2066,7 +1989,7 @@ private: markVarShadowed(); if (shadow->varList) { for (auto name : shadow->varList->names.objects()) { - addToAllowList(toString(name)); + addToAllowList(_parser.toString(name)); } } } @@ -2085,14 +2008,14 @@ private: auto def = static_cast(_def); auto& arg = argItems.emplace_back(); switch (def->name->getId()) { - case "Variable"_id: arg.name = toString(def->name); break; + case "Variable"_id: arg.name = _parser.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.name = _parser.toString(clsName->name); arg.assignSelf = s("self.__class."sv) + arg.name; break; } @@ -2102,7 +2025,7 @@ private: case "self_name"_id: { auto sfName = static_cast(selfName->name.get()); - arg.name = toString(sfName->name); + arg.name = _parser.toString(sfName->name); arg.assignSelf = s("self."sv) + arg.name; break; } @@ -2117,7 +2040,7 @@ private: forceAddToScope(arg.name); if (def->defaultValue) { pushScope(); - auto expList = toAst(arg.name, ExpList, x); + auto expList = toAst(arg.name, x); auto assign = x->new_ptr(); assign->values.push_back(def->defaultValue.get()); auto assignment = x->new_ptr(); @@ -2164,15 +2087,15 @@ private: switch (name->getId()) { case "self_class_name"_id: { auto clsName = static_cast(name); - auto nameStr = toString(clsName->name); - if (State::luaKeywords.find(nameStr) != State::luaKeywords.end()) { + auto nameStr = _parser.toString(clsName->name); + if (LuaKeywords.find(nameStr) != LuaKeywords.end()) { out.push_back(s("self.__class[\""sv) + nameStr + s("\"]")); if (invoke) { if (auto invokePtr = invoke.as()) { - invokePtr->args.push_front(toAst("self.__class"sv, Exp, x)); + invokePtr->args.push_front(toAst("self.__class"sv, x)); } else { auto invokeArgsPtr = invoke.as(); - invokeArgsPtr->args.push_front(toAst("self.__class"sv, Exp, x)); + invokeArgsPtr->args.push_front(toAst("self.__class"sv, x)); } } } else { @@ -2185,15 +2108,15 @@ private: break; case "self_name"_id: { auto sfName = static_cast(name); - auto nameStr = toString(sfName->name); - if (State::luaKeywords.find(nameStr) != State::luaKeywords.end()) { + auto nameStr = _parser.toString(sfName->name); + if (LuaKeywords.find(nameStr) != LuaKeywords.end()) { out.push_back(s("self[\""sv) + nameStr + s("\"]")); if (invoke) { if (auto invokePtr = invoke.as()) { - invokePtr->args.push_front(toAst("self"sv, Exp, x)); + invokePtr->args.push_front(toAst("self"sv, x)); } else { auto invokeArgsPtr = invoke.as(); - invokeArgsPtr->args.push_front(toAst("self"sv, Exp, x)); + invokeArgsPtr->args.push_front(toAst("self"sv, x)); } } } else { @@ -2220,8 +2143,8 @@ private: auto value = x->new_ptr(); value->item.set(chainValue); auto opValue = x->new_ptr(); - opValue->op.set(toAst("!="sv, BinaryOperator, x)); - opValue->value.set(toAst("nil"sv, Value, x)); + opValue->op.set(toAst("!="sv, x)); + opValue->value.set(toAst("nil"sv, x)); auto exp = x->new_ptr(); exp->value.set(value); exp->opValues.push_back(opValue); @@ -2281,7 +2204,7 @@ private: auto colonItem = x->new_ptr(); colonItem->name.set(sname->name); partOne->items.pop_back(); - partOne->items.push_back(toAst("@"sv, Callable, x)); + partOne->items.push_back(toAst("@"sv, x)); partOne->items.push_back(colonItem); break; } @@ -2289,7 +2212,7 @@ private: auto colonItem = x->new_ptr(); colonItem->name.set(cname->name); partOne->items.pop_back(); - partOne->items.push_back(toAst("@@"sv, Callable, x)); + partOne->items.push_back(toAst("@@"sv, x)); partOne->items.push_back(colonItem); break; } @@ -2303,9 +2226,9 @@ private: chainValue->items.pop_back(); if (chainValue->items.empty()) { if (_withVars.empty()) { - throw std::logic_error(debugInfo("Short dot/colon syntax must be called within a with block."sv, x)); + throw std::logic_error(_info.errorMessage("Short dot/colon syntax must be called within a with block."sv, x)); } - chainValue->items.push_back(toAst(_withVars.top(), Callable, x)); + chainValue->items.push_back(toAst(_withVars.top(), x)); } auto newObj = singleVariableFrom(chainValue); if (!newObj.empty()) { @@ -2318,7 +2241,7 @@ private: auto assign = x->new_ptr(); assign->values.push_back(exp); auto expListAssign = x->new_ptr(); - expListAssign->expList.set(toAst(objVar, ExpList, x)); + expListAssign->expList.set(toAst(objVar, x)); expListAssign->action.set(assign); transformAssignment(expListAssign, temp); } @@ -2329,16 +2252,16 @@ private: } dotItem->name.set(name); partOne->items.clear(); - partOne->items.push_back(toAst(objVar, Callable, x)); + partOne->items.push_back(toAst(objVar, x)); partOne->items.push_back(dotItem); auto it = opIt; ++it; if (it != chainList.end() && ast_is(*it)) { if (auto invoke = ast_cast(*it)) { - invoke->args.push_front(toAst(objVar, Exp, x)); + invoke->args.push_front(toAst(objVar, x)); } else { auto invokeArgs = static_cast(*it); - invokeArgs->args.push_front(toAst(objVar, Exp, x)); + invokeArgs->args.push_front(toAst(objVar, x)); } } objVar = getUnusedName("_obj_"sv); @@ -2350,7 +2273,7 @@ private: auto assign = x->new_ptr(); assign->values.push_back(exp); auto expListAssign = x->new_ptr(); - expListAssign->expList.set(toAst(objVar, ExpList, x)); + expListAssign->expList.set(toAst(objVar, x)); expListAssign->action.set(assign); transformAssignment(expListAssign, temp); } @@ -2358,7 +2281,7 @@ private: temp.push_back(clearBuf()); pushScope(); auto partTwo = x->new_ptr(); - partTwo->items.push_back(toAst(objVar, Callable, x)); + partTwo->items.push_back(toAst(objVar, x)); for (auto it = ++opIt;it != chainList.end();++it) { partTwo->items.push_back(*it); } @@ -2434,9 +2357,9 @@ private: 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())); + throw std::logic_error(_info.errorMessage("Short dot/colon syntax must be called within a with block."sv, chainList.front())); } else { - baseChain->items.push_back(toAst(_withVars.top(), Callable, x)); + baseChain->items.push_back(toAst(_withVars.top(), x)); } break; } @@ -2445,7 +2368,7 @@ private: baseChain->items.push_back(*it); } auto colonChainItem = static_cast(chainList.back()); - auto funcName = toString(colonChainItem->name); + auto funcName = _parser.toString(colonChainItem->name); auto baseVar = getUnusedName("_base_"sv); auto fnVar = getUnusedName("_fn_"sv); { @@ -2456,19 +2379,19 @@ private: auto assign = x->new_ptr(); assign->values.push_back(exp); auto assignment = x->new_ptr(); - assignment->expList.set(toAst(baseVar, ExpList, x)); + assignment->expList.set(toAst(baseVar, x)); assignment->action.set(assign); transformAssignment(assignment, temp); } { auto assign = x->new_ptr(); - assign->values.push_back(toAst(baseVar + "." + funcName, Exp, x)); + assign->values.push_back(toAst(baseVar + "." + funcName, x)); auto assignment = x->new_ptr(); - assignment->expList.set(toAst(fnVar, ExpList, x)); + assignment->expList.set(toAst(fnVar, x)); assignment->action.set(assign); transformAssignment(assignment, temp); } - auto funLit = toAst(fnVar + s(" and (...)-> "sv) + fnVar + s(" "sv) + baseVar + s(", ..."sv), Exp, x); + auto funLit = toAst(fnVar + s(" and (...)-> "sv) + fnVar + s(" "sv) + baseVar + s(", ..."sv), x); switch (usage) { case ExpUsage::Closure: case ExpUsage::Return: { @@ -2516,7 +2439,7 @@ private: 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, x)); + throw std::logic_error(_info.errorMessage("Short dot/colon syntax must be called within a with block."sv, x)); } else { temp.push_back(_withVars.top()); } @@ -2548,7 +2471,7 @@ private: --next; } if (!ast_is(followItem)) { - throw std::logic_error(debugInfo("Colon chain item must be followed by invoke arguments."sv, colonItem)); + throw std::logic_error(_info.errorMessage("Colon chain item must be followed by invoke arguments."sv, colonItem)); } if (colonItem->name.is()) { std::string callVar; @@ -2558,7 +2481,7 @@ private: switch (chainList.front()->getId()) { case "DotChainItem"_id: case "ColonChainItem"_id: - chainValue->items.push_back(toAst(_withVars.top(), Callable, x)); + chainValue->items.push_back(toAst(_withVars.top(), x)); break; } for (auto i = chainList.begin(); i != current; ++i) { @@ -2572,7 +2495,7 @@ private: if (callVar.empty()) { callVar = getUnusedName(s("_call_"sv)); auto assignment = x->new_ptr(); - assignment->expList.set(toAst(callVar, ExpList, x)); + assignment->expList.set(toAst(callVar, x)); auto assign = x->new_ptr(); assign->values.push_back(exp); assignment->action.set(assign); @@ -2582,18 +2505,18 @@ private: } } { - auto name = toString(colonItem->name); + auto name = _parser.toString(colonItem->name); auto chainValue = x->new_ptr(); - chainValue->items.push_back(toAst(callVar, Callable, x)); + chainValue->items.push_back(toAst(callVar, x)); if (ast_is(*current)) { chainValue->items.push_back(x->new_ptr()); } - chainValue->items.push_back(toAst(s("\""sv) + name + s("\""sv), Exp, x)); + chainValue->items.push_back(toAst(s("\""sv) + name + s("\""sv), x)); if (auto invoke = ast_cast(followItem)) { - invoke->args.push_front(toAst(callVar, Exp, x)); + invoke->args.push_front(toAst(callVar, x)); } else { auto invokeArgs = static_cast(followItem); - invokeArgs->args.push_front(toAst(callVar, Exp, x)); + invokeArgs->args.push_front(toAst(callVar, x)); } for (auto i = next; i != chainList.end(); ++i) { chainValue->items.push_back(*i); @@ -2629,7 +2552,7 @@ private: } auto body = x->new_ptr(); body->content.set(block); - auto funLit = toAst("->"sv, FunLit, x); + auto funLit = toAst("->"sv, x); funLit->body.set(body); auto simpleValue = x->new_ptr(); simpleValue->value.set(funLit); @@ -2708,8 +2631,8 @@ private: } void transformDotChainItem(DotChainItem_t* dotChainItem, str_list& out) { - auto name = toString(dotChainItem->name); - if (State::keywords.find(name) != State::keywords.end()) { + auto name = _parser.toString(dotChainItem->name); + if (Keywords.find(name) != Keywords.end()) { out.push_back(s("[\""sv) + name + s("\"]"sv)); } else { out.push_back(s("."sv) + name); @@ -2717,12 +2640,12 @@ private: } void transformColonChainItem(ColonChainItem_t* colonChainItem, str_list& out) { - auto name = toString(colonChainItem->name); + auto name = _parser.toString(colonChainItem->name); out.push_back(s(colonChainItem->switchToDot ? "."sv : ":"sv) + name); } void transformSlice(Slice_t* slice, str_list&) { - throw std::logic_error(debugInfo("Slice syntax not supported here."sv, slice)); + throw std::logic_error(_info.errorMessage("Slice syntax not supported here."sv, slice)); } void transformInvoke(Invoke_t* invoke, str_list& out) { @@ -2740,18 +2663,18 @@ private: } 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); + std::string op = _parser.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, ExpUsage::Closure); out.push_back(join(temp)); } void transformVariable(Variable_t* name, str_list& out) { - out.push_back(toString(name)); + out.push_back(_parser.toString(name)); } void transformNum(Num_t* num, str_list& out) { - out.push_back(toString(num)); + out.push_back(_parser.toString(num)); } void transformTableLit(TableLit_t* table, str_list& out) { @@ -2830,7 +2753,7 @@ private: } } { - auto assignLeft = toAst(accumVar + s("["sv) + lenVar + s("]"sv), ExpList, x); + auto assignLeft = toAst(accumVar + s("["sv) + lenVar + s("]"sv), x); auto assign = x->new_ptr(); assign->values.push_back(comp->value); auto assignment = x->new_ptr(); @@ -2865,7 +2788,7 @@ private: case ExpUsage::Assignment: { out.push_back(clearBuf()); auto assign = x->new_ptr(); - assign->values.push_back(toAst(accumVar, Exp, x)); + assign->values.push_back(toAst(accumVar, x)); auto assignment = x->new_ptr(); assignment->expList.set(assignList); assignment->action.set(assign); @@ -2900,7 +2823,7 @@ private: break; case "TableLit"_id: { auto desVar = getUnusedName("_des_"sv); - destructPairs.emplace_back(item, toAst(desVar, Exp, x)); + destructPairs.emplace_back(item, toAst(desVar, x)); vars.push_back(desVar); varAfter.push_back(desVar); break; @@ -2915,7 +2838,7 @@ private: 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)); + if (!value) throw std::logic_error(_info.errorMessage("Invalid star syntax."sv, star_exp)); bool endWithSlice = false; BLOCK_START auto chainValue = value->item.as(); @@ -3049,7 +2972,7 @@ private: void transformForHead(For_t* forNode, str_list& out) { str_list temp; - std::string varName = toString(forNode->varName); + std::string varName = _parser.toString(forNode->varName); transformExp(forNode->startValue, temp, ExpUsage::Closure); transformExp(forNode->stopValue, temp, ExpUsage::Closure); if (forNode->stepValue) { @@ -3075,7 +2998,7 @@ private: case "ForEach"_id: return traversal::Return; case "BreakLoop"_id: { - return toString(node) == "continue"sv ? + return _parser.toString(node) == "continue"sv ? traversal::Stop : traversal::Return; } default: @@ -3128,7 +3051,7 @@ private: _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); + auto expList = toAst(accum + s("["sv) + len + s("]"sv), x); assignLastExplist(expList, forNode->body); auto lenLine = len + s(" = "sv) + len + s(" + 1"sv) + nlr(forNode->body); transformLoopBody(forNode->body, out, lenLine); @@ -3156,7 +3079,7 @@ private: pushScope(); auto accum = transformForInner(forNode, temp); auto assign = x->new_ptr(); - assign->values.push_back(toAst(accum, Exp, x)); + assign->values.push_back(toAst(accum, x)); auto assignment = x->new_ptr(); assignment->expList.set(assignExpList); assignment->action.set(assign); @@ -3166,7 +3089,7 @@ private: } else { auto accum = transformForInner(forNode, temp); auto returnNode = x->new_ptr(); - auto expListLow = toAst(accum, ExpListLow, x); + auto expListLow = toAst(accum, x); returnNode->valueList.set(expListLow); transformReturn(returnNode, temp); } @@ -3174,7 +3097,7 @@ private: } void transformBinaryOperator(BinaryOperator_t* node, str_list& out) { - auto op = toString(node); + auto op = _parser.toString(node); out.push_back(op == "!="sv ? s("~="sv) : op); } @@ -3196,7 +3119,7 @@ private: _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); + auto expList = toAst(accum + s("["sv) + len + s("]"sv), x); assignLastExplist(expList, forEach->body); auto lenLine = len + s(" = "sv) + len + s(" + 1"sv) + nlr(forEach->body); transformLoopBody(forEach->body, out, lenLine); @@ -3224,7 +3147,7 @@ private: pushScope(); auto accum = transformForEachInner(forEach, temp); auto assign = x->new_ptr(); - assign->values.push_back(toAst(accum, Exp, x)); + assign->values.push_back(toAst(accum, x)); auto assignment = x->new_ptr(); assignment->expList.set(assignExpList); assignment->action.set(assign); @@ -3234,7 +3157,7 @@ private: } else { auto accum = transformForEachInner(forEach, temp); auto returnNode = x->new_ptr(); - auto expListLow = toAst(accum, ExpListLow, x); + auto expListLow = toAst(accum, x); returnNode->valueList.set(expListLow); transformReturn(returnNode, temp); } @@ -3242,7 +3165,7 @@ private: } void transform_variable_pair(variable_pair_t* pair, str_list& out) { - auto name = toString(pair->name); + auto name = _parser.toString(pair->name); out.push_back(name + s(" = "sv) + name); } @@ -3252,7 +3175,7 @@ private: switch (key->getId()) { case "KeyName"_id: { transformKeyName(static_cast(key), temp); - if (State::luaKeywords.find(temp.back()) != State::luaKeywords.end()) { + if (LuaKeywords.find(temp.back()) != LuaKeywords.end()) { temp.back() = s("[\""sv) + temp.back() + s("\"]"); } break; @@ -3283,30 +3206,22 @@ private: auto name = keyName->name.get(); switch (name->getId()) { case "SelfName"_id: transformSelfName(static_cast(name), out); break; - case "Name"_id: out.push_back(toString(name)); break; + case "Name"_id: out.push_back(_parser.toString(name)); break; default: break; } } - void replace(std::string& str, std::string_view from, std::string_view to) const { - 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, ""); + auto content = _parser.toString(luaString->content); + Utils::replace(content, "\r"sv, ""); if (content[0] == '\n') content.erase(content.begin()); - out.push_back(toString(luaString->open) + content + toString(luaString->close)); + out.push_back(_parser.toString(luaString->open) + content + _parser.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); + auto str = _parser.toString(singleString); + Utils::replace(str, "\r"sv, ""); + Utils::replace(str, "\n"sv, "\\n"sv); out.push_back(str); } @@ -3317,9 +3232,9 @@ private: 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); + auto str = _parser.toString(content); + Utils::replace(str, "\r"sv, ""); + Utils::replace(str, "\n"sv, "\\n"sv); temp.push_back(s("\""sv) + str + s("\""sv)); break; } @@ -3345,7 +3260,7 @@ private: std::pair defineClassVariable(Assignable_t* assignable) { if (auto variable = assignable->item.as()) { - auto name = toString(variable); + auto name = _parser.toString(variable); if (addToScope(name)) { return {name, true}; } else { @@ -3375,7 +3290,7 @@ private: std::string assignItem; if (assignable) { if (!isAssignable(assignable)) { - throw std::logic_error(debugInfo("Left hand expression is not assignable."sv, assignable)); + throw std::logic_error(_info.errorMessage("Left hand expression is not assignable."sv, assignable)); } bool newDefined = false; std::tie(className, newDefined) = defineClassVariable(assignable); @@ -3385,7 +3300,7 @@ private: 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); + className = s("\""sv) + _parser.toString(dotChain->name) + s("\""sv); } else if (auto index = ast_cast(chain->items.back())) { if (auto name = index->getByPath()) { transformString(name, temp); @@ -3517,7 +3432,7 @@ private: str_list tmp; if (usage == ExpUsage::Assignment) { auto assign = x->new_ptr(); - assign->values.push_back(toAst(classVar, Exp, x)); + assign->values.push_back(toAst(classVar, x)); auto assignment = x->new_ptr(); assignment->expList.set(expList); assignment->action.set(assign); @@ -3616,16 +3531,16 @@ private: 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); + if (!name) throw std::logic_error(_info.errorMessage("Invalid class poperty name."sv, selfName->name)); + newSuperCall = classVar + s(".__parent."sv) + _parser.toString(name->name); } else { auto x = keyName; auto nameNode = keyName->name.as(); if (!nameNode) break; - auto name = toString(nameNode); + auto name = _parser.toString(nameNode); if (name == "new"sv) { type = MemType::Builtin; - keyName->name.set(toAst("__init"sv, Name, x)); + keyName->name.set(toAst("__init"sv, x)); newSuperCall = classVar + s(".__parent.__init"sv); } else { newSuperCall = classVar + s(".__parent.__base."sv) + name; @@ -3636,18 +3551,18 @@ private: if (auto chainValue = ast_cast(node)) { if (auto callable = ast_cast(chainValue->items.front())) { auto var = callable->item.get(); - if (toString(var) == "super"sv) { + if (_parser.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)); + invoke->args.push_front(toAst("self"sv, x)); return true; } case "Invoke"_id: { auto invoke = static_cast(item); - invoke->args.push_front(toAst("self"sv, Exp, x)); + invoke->args.push_front(toAst("self"sv, x)); return true; } default: @@ -3669,7 +3584,7 @@ private: } else { newSuperCall = classVar + s(".__parent"sv); } - auto newChain = toAst(newSuperCall, ChainValue, chainValue); + auto newChain = toAst(newSuperCall, chainValue); chainValue->items.pop_front(); const auto& items = newChain->items.objects(); for (auto it = items.rbegin(); it != items.rend(); ++it) { @@ -3742,7 +3657,7 @@ private: if (withVar.empty()) { withVar = getUnusedName("_with_"sv); auto assignment = x->new_ptr(); - assignment->expList.set(toAst(withVar, ExpList, x)); + assignment->expList.set(toAst(withVar, x)); auto assign = x->new_ptr(); assign->values.push_back(with->assigns->values.objects().front()); assignment->action.set(assign); @@ -3756,7 +3671,7 @@ private: auto assignment = x->new_ptr(); assignment->expList.set(with->valueList); auto assign = x->new_ptr(); - assign->values.push_back(toAst(withVar, Exp, x)); + assign->values.push_back(toAst(withVar, x)); bool skipFirst = true; for (auto value : with->assigns->values.objects()) { if (skipFirst) { @@ -3784,7 +3699,7 @@ private: if (withVar.empty()) { withVar = getUnusedName("_with_"sv); auto assignment = x->new_ptr(); - assignment->expList.set(toAst(withVar, ExpList, x)); + assignment->expList.set(toAst(withVar, x)); auto assign = x->new_ptr(); assign->values.dup(with->valueList->exprs); assignment->action.set(assign); @@ -3829,7 +3744,7 @@ private: } if (clsDecl) { auto variable = clsDecl->name.as(); - if (!isDefined(toString(variable))) return traversal::Stop; + if (!isDefined(_parser.toString(variable))) return traversal::Stop; } return traversal::Return; } @@ -3848,7 +3763,7 @@ private: auto assignment = x->new_ptr(); assignment->expList.set(assignList); auto assign = x->new_ptr(); - assign->values.push_back(toAst(withVar, Exp, x)); + assign->values.push_back(toAst(withVar, x)); assignment->action.set(assign); transformAssignment(assignment, temp); } @@ -3866,7 +3781,7 @@ private: } void transform_const_value(const_value_t* const_value, str_list& out) { - out.push_back(toString(const_value)); + out.push_back(_parser.toString(const_value)); } void transformExport(Export_t* exportNode, str_list& out) { @@ -3877,13 +3792,13 @@ private: auto classDecl = static_cast(item); if (classDecl->name && classDecl->name->item->getId() == "Variable"_id) { markVarExported(ExportMode::Any, true); - addExportedVar(toString(classDecl->name->item)); + addExportedVar(_parser.toString(classDecl->name->item)); } transformClassDecl(classDecl, out, ExpUsage::Common); break; } case "export_op"_id: - if (toString(item) == "*"sv) { + if (_parser.toString(item) == "*"sv) { markVarExported(ExportMode::Any, false); } else { markVarExported(ExportMode::Capital, false); @@ -3895,7 +3810,7 @@ private: if (values->valueList) { auto expList = x->new_ptr(); for (auto name : values->nameList->names.objects()) { - addExportedVar(toString(name)); + addExportedVar(_parser.toString(name)); auto callable = x->new_ptr(); callable->item.set(name); auto chainValue = x->new_ptr(); @@ -3914,7 +3829,7 @@ private: transformAssignment(assignment, out); } else { for (auto name : values->nameList->names.objects()) { - addExportedVar(toString(name)); + addExportedVar(_parser.toString(name)); } } break; @@ -4011,7 +3926,7 @@ private: case ExpUsage::Assignment: { out.push_back(clearBuf()); auto assign = x->new_ptr(); - assign->values.push_back(toAst(tbl, Exp, x)); + assign->values.push_back(toAst(tbl, x)); auto assignment = x->new_ptr(); assignment->expList.set(assignList); assignment->action.set(assign); @@ -4032,7 +3947,7 @@ private: void transformCompFor(CompFor_t* comp, str_list& out) { str_list temp; - std::string varName = toString(comp->varName); + std::string varName = _parser.toString(comp->varName); transformExp(comp->startValue, temp, ExpUsage::Closure); transformExp(comp->stopValue, temp, ExpUsage::Closure); if (comp->stepValue) { @@ -4081,7 +3996,7 @@ private: ast_ptr objAssign; if (objVar.empty()) { objVar = getUnusedName("_obj_"sv); - auto expList = toAst(objVar, ExpList, x); + auto expList = toAst(objVar, x); auto assign = x->new_ptr(); assign->values.push_back(import->exp); auto assignment = x->new_ptr(); @@ -4096,7 +4011,7 @@ private: case "Variable"_id: { auto var = ast_to(name); { - auto callable = toAst(objVar, Callable, x); + auto callable = toAst(objVar, x); auto dotChainItem = x->new_ptr(); dotChainItem->name.set(var->name); auto chainValue = x->new_ptr(); @@ -4123,7 +4038,7 @@ private: auto var = static_cast(name)->name.get(); { auto nameNode = var->name.get(); - auto callable = toAst(objVar, Callable, x); + auto callable = toAst(objVar, x); auto colonChain = x->new_ptr(); colonChain->name.set(nameNode); auto chainValue = x->new_ptr(); @@ -4171,10 +4086,10 @@ private: void transformImportAs(ImportAs_t* import, str_list& out) { auto x = import; if (!import->target) { - auto name = toString(import->literal->inners.back()); - replace(name, "-"sv, "_"sv); - replace(name, " "sv, "_"sv); - import->target.set(toAst(name, Variable, x)); + auto name = _parser.toString(import->literal->inners.back()); + Utils::replace(name, "-"sv, "_"sv); + Utils::replace(name, " "sv, "_"sv); + import->target.set(toAst(name, x)); } auto target = import->target.get(); auto value = x->new_ptr(); @@ -4195,7 +4110,7 @@ private: auto assignList = x->new_ptr(); assignList->exprs.push_back(exp); auto assign = x->new_ptr(); - assign->values.push_back(toAst(s("require ") + toString(import->literal), Exp, x)); + assign->values.push_back(toAst(s("require ") + _parser.toString(import->literal), x)); auto assignment = x->new_ptr(); assignment->expList.set(assignList); assignment->action.set(assign); @@ -4232,7 +4147,7 @@ private: transformExp(whileNode->condition, temp, ExpUsage::Closure); 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); + auto assignLeft = toAst(accumVar + s("["sv) + lenVar + s("]"sv), x); assignLastExplist(assignLeft, whileNode->body); auto lenLine = lenVar + s(" = "sv) + lenVar + s(" + 1"sv) + nlr(whileNode); transformLoopBody(whileNode->body, temp, lenLine); @@ -4240,7 +4155,7 @@ private: temp.push_back(indent() + s("end"sv) + nlr(whileNode)); if (expList) { auto assign = x->new_ptr(); - assign->values.push_back(toAst(accumVar, Exp, x)); + assign->values.push_back(toAst(accumVar, x)); auto assignment = x->new_ptr(); assignment->expList.set(expList); assignment->action.set(assign); @@ -4269,7 +4184,7 @@ private: transformExp(whileNode->condition, temp, ExpUsage::Closure); 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); + auto assignLeft = toAst(accumVar + s("["sv) + lenVar + s("]"sv), x); assignLastExplist(assignLeft, whileNode->body); auto lenLine = lenVar + s(" = "sv) + lenVar + s(" + 1"sv) + nlr(whileNode); transformLoopBody(whileNode->body, temp, lenLine); @@ -4363,12 +4278,12 @@ private: } void transformBreakLoop(BreakLoop_t* breakLoop, str_list& out) { - auto keyword = toString(breakLoop); + auto keyword = _parser.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)); + if (_continueVars.empty()) throw std::logic_error(_info.errorMessage("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()); diff --git a/src/MoonP/moon_parser.cpp b/src/MoonP/moon_parser.cpp index baea9bf..60096af 100644 --- a/src/MoonP/moon_parser.cpp +++ b/src/MoonP/moon_parser.cpp @@ -12,7 +12,7 @@ namespace pl = parserlib; namespace MoonP { -std::unordered_set State::luaKeywords = { +std::unordered_set LuaKeywords = { "and", "break", "do", "else", "elseif", "end", "false", "for", "function", "if", "in", "local", "nil", "not", "or", @@ -20,7 +20,7 @@ std::unordered_set State::luaKeywords = { "while" }; -std::unordered_set State::keywords = { +std::unordered_set Keywords = { "and", "break", "do", "else", "elseif", "end", "false", "for", "function", "if", "in", "local", "nil", "not", "or", @@ -31,513 +31,561 @@ std::unordered_set State::keywords = { "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 multi_line_open = expr("--[["); -rule multi_line_close = expr("]]"); -rule multi_line_content = *(not_(multi_line_close) >> Any); -rule MultiLineComment = multi_line_open >> multi_line_content >> multi_line_close; -rule Indent = plain_space; -rule EscapeNewLine = expr('\\') >> plain_space >> -Comment >> Break; -rule Space = *(set(" \t") | MultiLineComment | EscapeNewLine) >> -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')) >> - -(-set("uU") >> set("lL") >> set("lL")) -) | ( - +range('0', '9') >> -set("uU") >> set("lL") >> set("lL") -) | ( +MoonParser::MoonParser() { + plain_space = *set(" \t"); + Break = nl(-expr('\r') >> '\n'); + Any = Break | any(); + White = *(set(" \t") | Break); + Stop = Break | eof(); + Comment = "--" >> *(not_(set("\r\n")) >> Any) >> and_(Stop); + multi_line_open = expr("--[["); + multi_line_close = expr("]]"); + multi_line_content = *(not_(multi_line_close) >> Any); + MultiLineComment = multi_line_open >> multi_line_content >> multi_line_close; + Indent = plain_space; + EscapeNewLine = expr('\\') >> plain_space >> -Comment >> Break; + Space = *(set(" \t") | MultiLineComment | EscapeNewLine) >> -Comment; + SomeSpace = +set(" \t") >> -Comment; + SpaceBreak = Space >> Break; + EmptyLine = SpaceBreak; + AlphaNum = range('a', 'z') | range('A', 'Z') | range('0', '9') | '_'; + Name = (range('a', 'z') | range('A', 'Z') | '_') >> *AlphaNum; + Num = ( - (+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 = pl::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 = pl::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 = pl::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; + "0x" >> + +(range('0', '9') | range('a', 'f') | range('A', 'F')) >> + -(-set("uU") >> set("lL") >> set("lL")) + ) | ( + +range('0', '9') >> -set("uU") >> set("lL") >> set("lL") + ) | ( + ( + (+range('0', '9') >> -('.' >> +range('0', '9'))) | + ('.' >> +range('0', '9')) + ) >> -(set("eE") >> -expr('-') >> +range('0', '9')) + ); + Cut = false_(); + 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)) + + Variable = pl::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 = Keywords.find(st->buffer); + st->buffer.clear(); + return it == Keywords.end(); + }); + + LuaKeyword = pl::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 = LuaKeywords.find(st->buffer); + st->buffer.clear(); + return it != LuaKeywords.end(); + }); + + self = expr('@'); + self_name = '@' >> Name; + self_class = expr("@@"); + self_class_name = "@@" >> Name; + + SelfName = Space >> (self_class_name | self_class | self_name | self); + KeyName = SelfName | Space >> Name; + VarArg = Space >> "..."; + + check_indent = pl::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 = pl::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; + }); + CheckIndent = and_(check_indent); + + advance = pl::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) { + 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; + }); + Advance = and_(advance); + + push_indent = pl::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; - } - return false; -}); -rule Advance = and_(advance); - -rule push_indent = pl::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 = pl::user(true_(), [](const item_t& item) { - State* st = reinterpret_cast(item.user_data); - st->indents.push(-1); - return true; -}); - -rule PopIndent = pl::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, TableLit; - -rule import_literal_inner = (range('a', 'z') | range('A', 'Z') | set("_-")) >> *(AlphaNum | '-'); -rule import_literal_chain = Seperator >> import_literal_inner >> *(expr('.') >> import_literal_inner); -rule ImportLiteral = sym('\'') >> import_literal_chain >> symx('\'') | sym('"') >> import_literal_chain >> symx('"'); - -rule ImportFrom = ImportNameList >> *SpaceBreak >> key("from") >> Exp; -rule ImportAs = ImportLiteral >> -(key("as") >> (Space >> Variable | TableLit)); - -rule Import = key("import") >> (ImportAs | ImportFrom); -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 >> - *(+SpaceBreak >> SwitchCase) >> - -(+SpaceBreak >> 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; + }); + PushIndent = and_(push_indent); -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 = pl::user(key("do") >> Body, [](const item_t& item) -{ - State* st = reinterpret_cast(item.user_data); - return st->doStack.empty() || st->doStack.top(); -}); - -rule DisableDo = pl::user(true_(), [](const item_t& item) -{ - State* st = reinterpret_cast(item.user_data); - st->doStack.push(false); - return true; -}); + PreventIndent = pl::user(true_(), [](const item_t& item) { + State* st = reinterpret_cast(item.user_data); + st->indents.push(-1); + return true; + }); -rule PopDo = pl::user(true_(), [](const item_t& item) -{ - State* st = reinterpret_cast(item.user_data); - st->doStack.pop(); - return true; -}); + PopIndent = pl::user(true_(), [](const item_t& item) { + State* st = reinterpret_cast(item.user_data); + st->indents.pop(); + return true; + }); -extern rule CompInner; + InBlock = Advance >> Block >> PopIndent; -rule Comprehension = sym('[') >> Exp >> CompInner >> sym(']'); -rule comp_value = sym(',') >> Exp; -rule TblComprehension = sym('{') >> (Exp >> -comp_value) >> CompInner >> sym('}'); + local_flag = expr('*') | expr('^'); + Local = key("local") >> ((Space >> local_flag) | NameList); -extern rule CompForEach, CompFor, CompClause; + colon_import_name = sym('\\') >> Space >> Variable; + ImportName = colon_import_name | Space >> Variable; + ImportNameList = Seperator >> *SpaceBreak >> ImportName >> *((+SpaceBreak | sym(',') >> *SpaceBreak) >> ImportName); -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; + import_literal_inner = (range('a', 'z') | range('A', 'Z') | set("_-")) >> *(AlphaNum | '-'); + import_literal_chain = Seperator >> import_literal_inner >> *(expr('.') >> import_literal_inner); + ImportLiteral = sym('\'') >> import_literal_chain >> symx('\'') | sym('"') >> import_literal_chain >> symx('"'); -extern rule TableBlock; + ImportFrom = ImportNameList >> *SpaceBreak >> key("from") >> Exp; + ImportAs = ImportLiteral >> -(key("as") >> (Space >> Variable | TableLit)); -rule Assign = sym('=') >> Seperator >> (With | If | Switch | TableBlock | Exp >> *((sym(',') | sym(';')) >> Exp)); + Import = key("import") >> (ImportAs | ImportFrom); + BreakLoop = (expr("break") | expr("continue")) >> not_(AlphaNum); -rule update_op = - expr("..") | - expr("+") | - expr("-") | - expr("*") | - expr("/") | - expr("%") | - expr("or") | - expr("and") | - expr("&") | - expr("|") | - expr(">>") | - expr("<<"); + Return = key("return") >> -ExpListLow; + WithExp = ExpList >> -Assign; -rule Update = Space >> update_op >> expr("=") >> Exp; + With = key("with") >> DisableDo >> ensure(WithExp, PopDo) >> -key("do") >> Body; + SwitchCase = key("when") >> ExpList >> -key("then") >> Body; + SwitchElse = key("else") >> Body; -rule BinaryOperator = - (expr("or") >> not_(AlphaNum)) | - (expr("and") >> not_(AlphaNum)) | - expr("<=") | - expr(">=") | - expr("~=") | - expr("!=") | - expr("==") | - expr("..") | - expr("<<") | - expr(">>") | - expr("//") | - set("+-*/%^><|&"); - -rule BackcallOperator = expr("|>"); - -extern rule AssignableChain; - -rule Assignable = AssignableChain | Space >> Variable | SelfName; - -extern rule Value; - -rule exp_op_value = Space >> (BackcallOperator | BinaryOperator) >> *SpaceBreak >> Value; -rule Exp = Value >> *exp_op_value; + SwitchBlock = *EmptyLine >> + Advance >> Seperator >> + SwitchCase >> + *(+SpaceBreak >> SwitchCase) >> + -(+SpaceBreak >> SwitchElse) >> + PopIndent; -extern rule Chain, Callable, InvokeArgs, existential_op; + Switch = key("switch") >> + DisableDo >> ensure(Exp, PopDo) >> + -key("do") >> -Space >> Break >> SwitchBlock; -rule ChainValue = Seperator >> (Chain | Callable) >> -existential_op >> -InvokeArgs; + IfCond = Exp >> -Assign; + IfElseIf = -(Break >> *EmptyLine >> CheckIndent) >> key("elseif") >> IfCond >> -key("then") >> Body; + IfElse = -(Break >> *EmptyLine >> CheckIndent) >> key("else") >> Body; + If = key("if") >> Seperator >> IfCond >> -key("then") >> Body >> *IfElseIf >> -IfElse; + Unless = key("unless") >> Seperator >> IfCond >> -key("then") >> Body >> *IfElseIf >> -IfElse; -extern rule KeyValue, String, SimpleValue; - -rule simple_table = Seperator >> KeyValue >> *(sym(',') >> KeyValue); -rule Value = SimpleValue | simple_table | ChainValue | String; - -extern rule LuaString; + While = key("while") >> DisableDo >> ensure(Exp, PopDo) >> -key("do") >> Body; -rule single_string_inner = expr("\\'") | "\\\\" | not_(expr('\'')) >> Any; -rule SingleString = symx('\'') >> *single_string_inner >> symx('\''); -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 >> symx('"'); -rule String = Space >> (DoubleString | SingleString | LuaString); - -rule lua_string_open = '[' >> *expr('=') >> '['; -rule lua_string_close = ']' >> *expr('=') >> ']'; - -rule LuaStringOpen = pl::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 = pl::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; -}); + for_step_value = sym(',') >> Exp; + for_args = Space >> Variable >> sym('=') >> Exp >> sym(',') >> Exp >> -for_step_value; -rule LuaStringContent = *(not_(LuaStringClose) >> Any); + For = key("for") >> DisableDo >> + ensure(for_args, PopDo) >> + -key("do") >> Body; -rule LuaString = pl::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 existential_op = expr('?'); -rule chain_call = (Callable | String) >> -existential_op >> ChainItems; -rule chain_item = and_(set(".\\")) >> ChainItems; -rule chain_dot_chain = DotChainItem >> -existential_op >> -ChainItems; - -rule Chain = chain_call | chain_item | - Space >> (chain_dot_chain | ColonChain); - -rule AssignableChain = Seperator >> Chain; + for_in = star_exp | ExpList; -extern rule ChainItem; + ForEach = key("for") >> AssignableNameList >> key("in") >> + DisableDo >> ensure(for_in, PopDo) >> + -key("do") >> Body; -rule chain_with_colon = +ChainItem >> -ColonChain; -rule ChainItems = chain_with_colon | ColonChain; + Do = pl::user(key("do") >> Body, [](const item_t& item) + { + State* st = reinterpret_cast(item.user_data); + return st->doStack.empty() || st->doStack.top(); + }); -extern rule Invoke, Slice; + DisableDo = pl::user(true_(), [](const item_t& item) + { + State* st = reinterpret_cast(item.user_data); + st->doStack.push(false); + return true; + }); -rule Index = symx('[') >> Exp >> sym(']'); -rule ChainItem = Invoke >> -existential_op | DotChainItem >> -existential_op | Slice | Index >> -existential_op; -rule DotChainItem = symx('.') >> Name; -rule ColonChainItem = symx('\\') >> (LuaKeyword | Name); -rule invoke_chain = Invoke >> -existential_op >> -ChainItems; -rule ColonChain = ColonChainItem >> -existential_op >> -invoke_chain; + PopDo = pl::user(true_(), [](const item_t& item) + { + State* st = reinterpret_cast(item.user_data); + st->doStack.pop(); + return true; + }); + + Comprehension = sym('[') >> Exp >> CompInner >> sym(']'); + comp_value = sym(',') >> Exp; + TblComprehension = sym('{') >> (Exp >> -comp_value) >> CompInner >> sym('}'); + + CompInner = Seperator >> (CompForEach | CompFor) >> *CompClause; + star_exp = sym('*') >> Exp; + CompForEach = key("for") >> AssignableNameList >> key("in") >> (star_exp | Exp); + CompFor = key("for") >> Space >> Variable >> sym('=') >> Exp >> sym(',') >> Exp >> -for_step_value; + CompClause = CompFor | CompForEach | key("when") >> Exp; + + Assign = sym('=') >> Seperator >> (With | If | Switch | TableBlock | Exp >> *((sym(',') | sym(';')) >> Exp)); + + update_op = + expr("..") | + expr("+") | + expr("-") | + expr("*") | + expr("/") | + expr("%") | + expr("or") | + expr("and") | + expr("&") | + expr("|") | + expr(">>") | + expr("<<"); + + Update = Space >> update_op >> expr("=") >> Exp; + + BinaryOperator = + (expr("or") >> not_(AlphaNum)) | + (expr("and") >> not_(AlphaNum)) | + expr("<=") | + expr(">=") | + expr("~=") | + expr("!=") | + expr("==") | + expr("..") | + expr("<<") | + expr(">>") | + expr("//") | + set("+-*/%^><|&"); + + BackcallOperator = expr("|>"); + + Assignable = AssignableChain | Space >> Variable | SelfName; + + exp_op_value = Space >> (BackcallOperator | BinaryOperator) >> *SpaceBreak >> Value; + Exp = Value >> *exp_op_value; + + ChainValue = Seperator >> (Chain | Callable) >> -existential_op >> -InvokeArgs; + + simple_table = Seperator >> KeyValue >> *(sym(',') >> KeyValue); + Value = SimpleValue | simple_table | ChainValue | String; + + single_string_inner = expr("\\'") | "\\\\" | not_(expr('\'')) >> Any; + SingleString = symx('\'') >> *single_string_inner >> symx('\''); + interp = symx("#{") >> Exp >> sym('}'); + double_string_plain = expr("\\\"") | "\\\\" | not_(expr('"')) >> Any; + double_string_inner = +(not_(interp) >> double_string_plain); + double_string_content = double_string_inner | interp; + DoubleString = symx('"') >> Seperator >> *double_string_content >> symx('"'); + String = Space >> (DoubleString | SingleString | LuaString); + + lua_string_open = '[' >> *expr('=') >> '['; + lua_string_close = ']' >> *expr('=') >> ']'; + + LuaStringOpen = pl::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 default_value = true_(); -rule Slice = - symx('[') >> - (Exp | default_value) >> - sym(',') >> - (Exp | default_value) >> - (sym(',') >> Exp | default_value) >> - sym(']'); + LuaStringClose = pl::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 Invoke = Seperator >> ( - FnArgs | - SingleString | - DoubleString | - and_(expr('[')) >> LuaString); + LuaStringContent = *(not_(LuaStringClose) >> Any); -extern rule TableValueList, TableLitLine; + LuaString = pl::user(LuaStringOpen >> -Break >> LuaStringContent >> LuaStringClose, [](const item_t& item) { + State* st = reinterpret_cast(item.user_data); + st->stringOpen = -1; + return true; + }); -rule TableValue = KeyValue | Exp; + Parens = sym('(') >> *SpaceBreak >> Exp >> *SpaceBreak >> sym(')'); + Callable = Space >> Variable | SelfName | VarArg | Parens; + FnArgsExpList = Exp >> *((Break | sym(',')) >> White >> Exp); -rule table_lit_lines = SpaceBreak >> TableLitLine >> *(-sym(',') >> SpaceBreak >> TableLitLine) >> -sym(','); + FnArgs = (symx('(') >> *SpaceBreak >> -FnArgsExpList >> *SpaceBreak >> sym(')')) | + (sym('!') >> not_(expr('='))); -rule TableLit = - sym('{') >> Seperator >> - -TableValueList >> - -sym(',') >> - -table_lit_lines >> - White >> sym('}'); - -rule TableValueList = TableValue >> *(sym(',') >> TableValue); - -rule TableLitLine = -( - PushIndent >> (TableValueList >> PopIndent | PopIndent) -) | ( - Space -); + existential_op = expr('?'); + chain_call = (Callable | String) >> -existential_op >> ChainItems; + chain_item = and_(set(".\\")) >> ChainItems; + chain_dot_chain = DotChainItem >> -existential_op >> -ChainItems; -extern rule KeyValueLine; + Chain = chain_call | chain_item | + Space >> (chain_dot_chain | ColonChain); -rule TableBlockInner = Seperator >> KeyValueLine >> *(+(SpaceBreak) >> KeyValueLine); -rule TableBlock = +(SpaceBreak) >> Advance >> ensure(TableBlockInner, PopIndent); + AssignableChain = Seperator >> Chain; -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; + chain_with_colon = +ChainItem >> -ColonChain; + ChainItems = chain_with_colon | ColonChain; -rule ClassDecl = - key("class") >> not_(expr(':')) >> - -Assignable >> - -(key("extends") >> PreventIndent >> ensure(Exp, PopIndent)) >> - -ClassBlock; + Index = symx('[') >> Exp >> sym(']'); + ChainItem = Invoke >> -existential_op | DotChainItem >> -existential_op | Slice | Index >> -existential_op; + DotChainItem = symx('.') >> Name; + ColonChainItem = symx('\\') >> (LuaKeyword | Name); + invoke_chain = Invoke >> -existential_op >> -ChainItems; + ColonChain = ColonChainItem >> -existential_op >> -invoke_chain; -rule export_values = NameList >> -(sym('=') >> ExpListLow); -rule export_op = expr('*') | expr('^'); -rule Export = key("export") >> (ClassDecl | (Space >> export_op) | export_values); + default_value = true_(); + Slice = + symx('[') >> + (Exp | default_value) >> + sym(',') >> + (Exp | default_value) >> + (sym(',') >> Exp | default_value) >> + sym(']'); -rule variable_pair = sym(':') >> not_(SomeSpace) >> Space >> Variable; + Invoke = Seperator >> ( + FnArgs | + SingleString | + DoubleString | + and_(expr('[')) >> LuaString); -rule normal_pair = -( - KeyName | - sym('[') >> Exp >> sym(']') | - Space >> DoubleString | - Space >> SingleString -) >> -symx(':') >> -(Exp | TableBlock | +(SpaceBreak) >> Exp); + TableValue = KeyValue | Exp; -rule KeyValue = variable_pair | normal_pair; + table_lit_lines = SpaceBreak >> TableLitLine >> *(-sym(',') >> SpaceBreak >> TableLitLine) >> -sym(','); -rule KeyValueList = KeyValue >> *(sym(',') >> KeyValue); -rule KeyValueLine = CheckIndent >> KeyValueList >> -sym(','); + TableLit = + sym('{') >> Seperator >> + -TableValueList >> + -sym(',') >> + -table_lit_lines >> + White >> sym('}'); -rule FnArgDef = (Space >> Variable | SelfName) >> -(sym('=') >> Exp); + TableValueList = TableValue >> *(sym(',') >> TableValue); -rule FnArgDefList = Seperator >> -( - ( - FnArgDef >> - *((sym(',') | Break) >> White >> FnArgDef) >> - -((sym(',') | Break) >> White >> VarArg) + TableLitLine = ( + PushIndent >> (TableValueList >> PopIndent | PopIndent) ) | ( - 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 Backcall = -FnArgsDef >> Space >> symx("<-") >> Space >> ChainValue; - -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 + Space ); -rule InvokeArgs = - not_(expr('-')) >> Seperator >> - ( - Exp >> *(sym(',') >> Exp) >> -(invoke_args_with_table | TableBlock) | - TableBlock + TableBlockInner = Seperator >> KeyValueLine >> *(+(SpaceBreak) >> KeyValueLine); + TableBlock = +(SpaceBreak) >> Advance >> ensure(TableBlockInner, PopIndent); + + class_member_list = Seperator >> KeyValue >> *(sym(',') >> KeyValue); + ClassLine = CheckIndent >> (class_member_list | Statement) >> -sym(','); + ClassBlock = +(SpaceBreak) >> Advance >>Seperator >> ClassLine >> *(+(SpaceBreak) >> ClassLine) >> PopIndent; + + ClassDecl = + key("class") >> not_(expr(':')) >> + -Assignable >> + -(key("extends") >> PreventIndent >> ensure(Exp, PopIndent)) >> + -ClassBlock; + + export_values = NameList >> -(sym('=') >> ExpListLow); + export_op = expr('*') | expr('^'); + Export = key("export") >> (ClassDecl | (Space >> export_op) | export_values); + + variable_pair = sym(':') >> not_(SomeSpace) >> Space >> Variable; + + normal_pair = ( + KeyName | + sym('[') >> Exp >> sym(']') | + Space >> DoubleString | + Space >> SingleString + ) >> + symx(':') >> + (Exp | TableBlock | +(SpaceBreak) >> Exp); + + KeyValue = variable_pair | normal_pair; + + KeyValueList = KeyValue >> *(sym(',') >> KeyValue); + KeyValueLine = CheckIndent >> KeyValueList >> -sym(','); + + FnArgDef = (Space >> Variable | SelfName) >> -(sym('=') >> Exp); + + FnArgDefList = Seperator >> ( + ( + FnArgDef >> + *((sym(',') | Break) >> White >> FnArgDef) >> + -((sym(',') | Break) >> White >> VarArg) + ) | ( + VarArg + ) ); -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 >> -Assign >> (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 | - Backcall | 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(); + outer_var_shadow = key("using") >> (NameList | Space >> expr("nil")); + + FnArgsDef = sym('(') >> White >> -FnArgDefList >> -outer_var_shadow >> White >> sym(')'); + fn_arrow = expr("->") | expr("=>"); + FunLit = -FnArgsDef >> Space >> fn_arrow >> -Body; + + NameList = Seperator >> Space >> Variable >> *(sym(',') >> Space >> Variable); + NameOrDestructure = Space >> Variable | TableLit; + AssignableNameList = Seperator >> NameOrDestructure >> *(sym(',') >> NameOrDestructure); + + Backcall = -FnArgsDef >> Space >> symx("<-") >> Space >> ChainValue; + + ExpList = Seperator >> Exp >> *(sym(',') >> Exp); + ExpListLow = Seperator >> Exp >> *((sym(',') | sym(';')) >> Exp); + + ArgLine = CheckIndent >> Exp >> *(sym(',') >> Exp); + ArgBlock = ArgLine >> *(sym(',') >> SpaceBreak >> ArgLine) >> PopIndent; + + invoke_args_with_table = + sym(',') >> + ( + TableBlock | + SpaceBreak >> Advance >> ArgBlock >> -TableBlock + ); + + InvokeArgs = + not_(expr('-')) >> Seperator >> + ( + Exp >> *(sym(',') >> Exp) >> -(invoke_args_with_table | TableBlock) | + TableBlock + ); + + const_value = (expr("nil") | expr("true") | expr("false")) >> not_(AlphaNum); + minus_exp = expr('-') >> not_(SomeSpace) >> Exp; + sharp_exp = expr('#') >> Exp; + tilde_exp = expr('~') >> Exp; + not_exp = expr("not") >> not_(AlphaNum) >> Exp; + unary_exp = minus_exp | sharp_exp | tilde_exp | not_exp; + + SimpleValue = + (Space >> const_value) | + If | Unless | Switch | With | ClassDecl | ForEach | For | While | Do | + (Space >> unary_exp) | + TblComprehension | TableLit | Comprehension | FunLit | + (Space >> Num); + + ExpListAssign = ExpList >> -(Update | Assign); + + if_else_line = key("if") >> Exp >> -Assign >> (key("else") >> Exp | default_value); + unless_line = key("unless") >> Exp; + + statement_appendix = (if_else_line | unless_line | CompInner) >> Space; + Statement = ( + Import | While | For | ForEach | + Return | Local | Export | Space >> BreakLoop | + Backcall | ExpListAssign + ) >> Space >> + -statement_appendix; + + Body = -Space >> Break >> *EmptyLine >> InBlock | Statement; + + empty_line_stop = Space >> and_(Stop); + Line = CheckIndent >> Statement | empty_line_stop; + Block = Seperator >> Line >> *(+Break >> Line); + + Shebang = expr("#!") >> *(not_(Stop) >> Any); + File = White >> -Shebang >> Block >> eof(); +} + +ParseInfo MoonParser::parse(const std::string& codes, rule& r) { + ParseInfo res; + try { + res.input = std::make_unique(); + *(res.input) = _converter.from_bytes(codes); + } catch (const std::range_error&) { + res.error = "Invalid text encoding."sv; + return res; + } + error_list errors; + try { + State state; + res.node.set(pl::parse(*(res.input), r, errors, &state)); + } catch (const std::logic_error& err) { + res.error = err.what(); + return res; + } + if (!errors.empty()) { + std::ostringstream buf; + for (error_list::iterator it = errors.begin(); it != errors.end(); ++it) { + const error& err = *it; + switch (err.m_type) { + case ERROR_TYPE::ERROR_SYNTAX_ERROR: + buf << res.errorMessage("Syntax error."sv, &err); + break; + case ERROR_TYPE::ERROR_INVALID_EOF: + buf << res.errorMessage("Invalid EOF."sv, &err); + break; + } + } + res.error = buf.str(); + } + return res; +} + +std::string MoonParser::toString(ast_node* node) { + return _converter.to_bytes(std::wstring(node->m_begin.m_it, node->m_end.m_it)); +} + +std::string MoonParser::toString(input::iterator begin, input::iterator end) { + return _converter.to_bytes(std::wstring(begin, end)); +} + +input MoonParser::encode(std::string_view input) { + return _converter.from_bytes(std::string(input)); +} + +std::string MoonParser::decode(const input& input) { + return _converter.to_bytes(input); +} + +namespace Utils { + 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(); + } + } +} + +std::string ParseInfo::errorMessage(std::string_view msg, const input_range* loc) const { + 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 = std::max(0, oldCol - 1); + auto it = begin; + for (int i = 0; i < oldCol; ++i) { + if (*it > ASCII) { + ++col; + } + ++it; + } + Utils::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(); +} } // namespace MoonP diff --git a/src/MoonP/moon_parser.h b/src/MoonP/moon_parser.h index fc4ee55..933aa7a 100644 --- a/src/MoonP/moon_parser.h +++ b/src/MoonP/moon_parser.h @@ -9,27 +9,266 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI #pragma once #include -#include #include #include #include #include +#include +#include +using namespace std::string_view_literals; #include "MoonP/ast.hpp" -using namespace parserlib; +#include "MoonP/moon_ast.h" namespace MoonP { -struct State { - State() { - indents.push(0); - stringOpen = -1; +struct ParseInfo { + ast_ptr node; + std::string error; + std::unique_ptr input; + std::string errorMessage(std::string_view msg, const input_range* loc) const; +}; + +#define AST_RULE(type) \ + rule type; \ + ast type##_impl = type; \ + template<> inline rule& getRule() { return type; } + +extern std::unordered_set LuaKeywords; +extern std::unordered_set Keywords; + +class MoonParser { +public: + MoonParser(); + + template + ParseInfo parse(const std::string& codes) { + error_list errors; + auto res = parse(codes, getRule()); + if (res.node.template is()) { + return res; + } + return res; + } + + template + bool match(const std::string& codes) { + auto rEnd = rule(getRule() >> eof()); + return parse(codes, rEnd).node; + } + + std::string toString(ast_node* node); + std::string toString(input::iterator begin, input::iterator end); + + input encode(std::string_view input); + std::string decode(const input& input); + +protected: + ParseInfo parse(const std::string& codes, rule& r); + + struct State { + State() { + indents.push(0); + stringOpen = -1; + } + std::string buffer; + size_t stringOpen; + std::stack indents; + std::stack doStack; + }; + +private: + Converter _converter; + + template + inline rule& getRule() { + assert(false); + return Cut; } - std::string buffer; - size_t stringOpen; - std::stack indents; - std::stack doStack; - static std::unordered_set luaKeywords; - static std::unordered_set keywords; + + rule plain_space; + rule Break; + rule Any; + rule White; + rule Stop; + rule Comment; + rule multi_line_open; + rule multi_line_close; + rule multi_line_content; + rule MultiLineComment; + rule Indent; + rule EscapeNewLine; + rule Space; + rule SomeSpace; + rule SpaceBreak; + rule EmptyLine; + rule AlphaNum; + rule Cut; + rule check_indent; + rule CheckIndent; + rule advance; + rule Advance; + rule push_indent; + rule PushIndent; + rule PreventIndent; + rule PopIndent; + rule InBlock; + rule ImportName; + rule ImportNameList; + rule import_literal_chain; + rule WithExp; + rule PopDo; + rule DisableDo; + rule SwitchElse; + rule SwitchBlock; + rule IfElseIf; + rule IfElse; + rule for_args; + rule for_in; + rule CompClause; + rule Chain; + rule KeyValue; + rule single_string_inner; + rule interp; + rule double_string_plain; + rule lua_string_open; + rule lua_string_close; + rule FnArgsExpList; + rule FnArgs; + rule chain_call; + rule chain_item; + rule ChainItems; + rule chain_dot_chain; + rule ColonChain; + rule chain_with_colon; + rule ChainItem; + rule Index; + rule invoke_chain; + rule TableValue; + rule table_lit_lines; + rule TableLitLine; + rule TableValueList; + rule TableBlockInner; + rule ClassLine; + rule KeyValueLine; + rule KeyValueList; + rule ArgLine; + rule ArgBlock; + rule invoke_args_with_table; + rule minus_exp; + rule sharp_exp; + rule tilde_exp; + rule not_exp; + rule empty_line_stop; + rule Line; + rule Shebang; + + AST_RULE(Num) + AST_RULE(Name) + AST_RULE(Variable) + AST_RULE(LuaKeyword) + AST_RULE(self) + AST_RULE(self_name) + AST_RULE(self_class) + AST_RULE(self_class_name) + AST_RULE(SelfName) + AST_RULE(KeyName) + AST_RULE(VarArg) + AST_RULE(local_flag) + AST_RULE(Seperator) + AST_RULE(NameList) + AST_RULE(Local) + AST_RULE(colon_import_name) + AST_RULE(import_literal_inner) + AST_RULE(ImportLiteral) + AST_RULE(ImportFrom) + AST_RULE(ImportAs) + AST_RULE(Import) + AST_RULE(Backcall) + AST_RULE(ExpListLow) + AST_RULE(ExpList) + AST_RULE(Return) + AST_RULE(With) + AST_RULE(SwitchCase) + AST_RULE(Switch) + AST_RULE(IfCond) + AST_RULE(If) + AST_RULE(Unless) + AST_RULE(While) + AST_RULE(for_step_value) + AST_RULE(For) + AST_RULE(ForEach) + AST_RULE(Do) + AST_RULE(Comprehension) + AST_RULE(comp_value) + AST_RULE(TblComprehension) + AST_RULE(star_exp) + AST_RULE(CompForEach) + AST_RULE(CompFor) + AST_RULE(CompInner) + AST_RULE(Assign) + AST_RULE(update_op) + AST_RULE(Update) + AST_RULE(BinaryOperator) + AST_RULE(BackcallOperator) + AST_RULE(Assignable) + AST_RULE(AssignableChain) + AST_RULE(exp_op_value) + AST_RULE(Exp) + AST_RULE(Callable) + AST_RULE(ChainValue) + AST_RULE(simple_table) + AST_RULE(SimpleValue) + AST_RULE(Value) + AST_RULE(LuaStringOpen); + AST_RULE(LuaStringContent); + AST_RULE(LuaStringClose); + AST_RULE(LuaString) + AST_RULE(SingleString) + AST_RULE(double_string_inner) + AST_RULE(double_string_content) + AST_RULE(DoubleString) + AST_RULE(String) + AST_RULE(Parens) + AST_RULE(DotChainItem) + AST_RULE(ColonChainItem) + AST_RULE(default_value) + AST_RULE(Slice) + AST_RULE(Invoke) + AST_RULE(existential_op) + AST_RULE(TableLit) + AST_RULE(TableBlock) + AST_RULE(class_member_list) + AST_RULE(ClassBlock) + AST_RULE(ClassDecl) + AST_RULE(export_values) + AST_RULE(export_op) + AST_RULE(Export) + AST_RULE(variable_pair) + AST_RULE(normal_pair) + AST_RULE(FnArgDef) + AST_RULE(FnArgDefList) + AST_RULE(outer_var_shadow) + AST_RULE(FnArgsDef) + AST_RULE(fn_arrow) + AST_RULE(FunLit) + AST_RULE(NameOrDestructure) + AST_RULE(AssignableNameList) + AST_RULE(InvokeArgs) + AST_RULE(const_value) + AST_RULE(unary_exp) + AST_RULE(ExpListAssign) + AST_RULE(if_else_line) + AST_RULE(unless_line) + AST_RULE(statement_appendix) + AST_RULE(BreakLoop) + AST_RULE(Statement) + AST_RULE(Body) + AST_RULE(Block) + AST_RULE(File) +}; + +namespace Utils { + void replace(std::string& str, std::string_view from, std::string_view to); }; } // namespace MoonP diff --git a/src/MoonP/parser.cpp b/src/MoonP/parser.cpp index 94f80af..cb896c2 100644 --- a/src/MoonP/parser.cpp +++ b/src/MoonP/parser.cpp @@ -21,25 +21,6 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 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: @@ -1175,14 +1156,19 @@ bool error::operator < (const error &e) const { return m_begin.m_it < e.m_begin.m_it; } +rule::rule() : + m_expr(nullptr), + m_parse_proc(nullptr) +{ +} /** character terminal constructor. @param c character. */ rule::rule(char c) : - m_expr(new _char(c)) + m_expr(new _char(c)), + m_parse_proc(nullptr) { - m_parse_proc = _get_parse_proc(this); } @@ -1190,9 +1176,9 @@ rule::rule(char c) : @param s null-terminated string. */ rule::rule(const char *s) : - m_expr(new _string(s)) + m_expr(new _string(s)), + m_parse_proc(nullptr) { - m_parse_proc = _get_parse_proc(this); } @@ -1200,9 +1186,9 @@ rule::rule(const char *s) : @param e expression. */ rule::rule(const expr &e) : - m_expr(_private::get_expr(e)) + m_expr(_private::get_expr(e)), + m_parse_proc(nullptr) { - m_parse_proc = _get_parse_proc(this); } @@ -1211,11 +1197,19 @@ rule::rule(const expr &e) : */ rule::rule(rule &r) : m_expr(new _ref(r)), - m_parse_proc(0) + m_parse_proc(nullptr) { - m_parse_proc = _get_parse_proc(this); } +rule& rule::operator = (rule & r) { + m_expr = new _ref(r); + return *this; +} + +rule &rule::operator = (const expr & e) { + m_expr = _private::get_expr(e); + return *this; +} /** invalid constructor from rule (required by gcc). @exception std::logic_error always thrown. @@ -1278,8 +1272,6 @@ expr rule::operator !() { 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; } diff --git a/src/MoonP/parser.hpp b/src/MoonP/parser.hpp index 9739465..b419e8c 100644 --- a/src/MoonP/parser.hpp +++ b/src/MoonP/parser.hpp @@ -28,16 +28,13 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND namespace parserlib { // const str hash helper functions -inline constexpr size_t hash(char const* input) -{ +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) -{ +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) -{ +inline size_t constexpr operator"" _id(const char* s, size_t) { return hash(s); } @@ -52,8 +49,7 @@ class _context; class rule; -struct item_t -{ +struct item_t { input_it begin; input_it end; void* user_data; @@ -74,7 +70,7 @@ public: int m_col; ///null constructor. - pos():m_line(-1),m_col(0) {} + pos():m_line(0),m_col(0) {} /** constructor from input. @param i input. @@ -216,6 +212,7 @@ public: /** character terminal constructor. @param c character. */ + rule(); rule(char c); /** null-terminated string terminal constructor. @@ -278,6 +275,10 @@ public: */ rule *this_ptr() { return this; } + rule &operator = (rule &); + + rule &operator = (const expr &); + private: //mode enum _MODE { @@ -308,9 +309,6 @@ private: //state _state m_state; - //assignment not allowed - rule &operator = (rule &); - friend class _private; friend class _context; }; diff --git a/src/moonc.cpp b/src/moonc.cpp index 4498bee..d04ce47 100644 --- a/src/moonc.cpp +++ b/src/moonc.cpp @@ -9,9 +9,9 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI #include #include #include +#include #include "MoonP/moon_compiler.h" -#include "MoonP/parser.hpp" -#include "MoonP/moon_ast.h" +#include "MoonP/moon_parser.h" int main(int narg, const char** args) { const char* help = @@ -82,87 +82,98 @@ int main(int narg, const char** args) { std::cout << "Error: -o can not be used with multiple input files.\n"; std::cout << help; } + if (targetPath.back() != '/' && targetPath.back() != '\\') { + targetPath.append("/"); + } + std::list()>>> results; for (const auto& file : files) { - std::ifstream input(file, input.in); - if (input) { - std::string s( - (std::istreambuf_iterator(input)), - std::istreambuf_iterator()); - if (dumpCompileTime) { - auto start = std::chrono::high_resolution_clock::now(); + auto task = std::async(std::launch::async, [=]() { + std::ifstream input(file, input.in); + if (input) { + std::string s( + (std::istreambuf_iterator(input)), + std::istreambuf_iterator()); + if (dumpCompileTime) { + auto start = std::chrono::high_resolution_clock::now(); + auto result = MoonP::moonCompile(s, config); + auto end = std::chrono::high_resolution_clock::now(); + if (!std::get<0>(result).empty()) { + std::chrono::duration diff = end - start; + start = std::chrono::high_resolution_clock::now(); + MoonP::MoonParser{}.parse(s); + end = std::chrono::high_resolution_clock::now(); + std::chrono::duration parseDiff = end - start; + std::cout << file << " \n"; + std::cout << "Parse time: " << std::setprecision(5) << parseDiff.count() * 1000 << " ms\n"; + std::cout << "Compile time: " << std::setprecision(5) << (diff.count() - parseDiff.count()) * 1000 << " ms\n\n"; + return 0; + } else { + std::cout << "Fail to compile: " << file << ".\n"; + std::cout << std::get<1>(result) << '\n'; + return 1; + } + } auto result = MoonP::moonCompile(s, config); - auto end = std::chrono::high_resolution_clock::now(); if (!std::get<0>(result).empty()) { - std::chrono::duration diff = end - start; - error_list el; - MoonP::State st; - start = std::chrono::high_resolution_clock::now(); - auto input = Converter{}.from_bytes(s); - parserlib::parse(input, MoonP::File, el, &st); - end = std::chrono::high_resolution_clock::now(); - std::chrono::duration parseDiff = end - start; - std::cout << file << " \n"; - std::cout << "Parse time: " << std::setprecision(5) << parseDiff.count() * 1000 << " ms\n"; - std::cout << "Compile time: " << std::setprecision(5) << (diff.count() - parseDiff.count()) * 1000 << " ms\n\n"; - } else { - std::cout << "Fail to compile: " << file << ".\n"; - std::cout << std::get<1>(result) << '\n'; - return 1; - } - continue; - } - auto result = MoonP::moonCompile(s, config); - if (!std::get<0>(result).empty()) { - if (!writeToFile) { - std::cout << std::get<0>(result) << '\n'; - } else { - std::string targetFile; - if (resultFile.empty()) { - std::string ext; - targetFile = file; - size_t pos = file.rfind('.'); - if (pos != std::string::npos) { - ext = file.substr(pos + 1); - for (size_t i = 0; i < ext.length(); i++) { - ext[i] = static_cast(tolower(ext[i])); - } - targetFile = file.substr(0, pos) + ".lua"; - } - if (!targetPath.empty()) { - std::string name; - pos = targetFile.find_last_of("/\\"); - if (pos == std::string::npos) { - name = targetFile; - } else { - name = targetFile.substr(pos + 1); + if (!writeToFile) { + std::cout << std::get<0>(result) << '\n'; + return 1; + } else { + std::string targetFile; + if (resultFile.empty()) { + std::string ext; + targetFile = file; + size_t pos = file.rfind('.'); + if (pos != std::string::npos) { + ext = file.substr(pos + 1); + for (size_t i = 0; i < ext.length(); i++) { + ext[i] = static_cast(tolower(ext[i])); + } + targetFile = file.substr(0, pos) + ".lua"; } - if (targetPath.back() != '/' && targetPath.back() != '\\') { - targetPath.append("/"); + if (!targetPath.empty()) { + std::string name; + pos = targetFile.find_last_of("/\\"); + if (pos == std::string::npos) { + name = targetFile; + } else { + name = targetFile.substr(pos + 1); + } + targetFile = targetPath + name; } - targetFile = targetPath + name; + } else { + targetFile = resultFile; + } + std::ofstream output(targetFile, output.trunc | output.out); + if (output) { + const auto& codes = std::get<0>(result); + output.write(codes.c_str(), codes.size()); + std::cout << "Built " << file << '\n'; + return 0; + } else { + std::cout << "Fail to write file: " << targetFile << ".\n"; + return 1; } - } else { - targetFile = resultFile; - } - std::ofstream output(targetFile, output.trunc | output.out); - if (output) { - const auto& codes = std::get<0>(result); - output.write(codes.c_str(), codes.size()); - std::cout << "Built " << file << '\n'; - } else { - std::cout << "Fail to write file: " << targetFile << ".\n"; - return 1; } + } else { + std::cout << "Fail to compile: " << file << ".\n"; + std::cout << std::get<1>(result) << '\n'; + return 1; } } else { - std::cout << "Fail to compile: " << file << ".\n"; - std::cout << std::get<1>(result) << '\n'; + std::cout << "Fail to read file: " << file << ".\n"; return 1; } - } else { - std::cout << "Fail to read file: " << file << ".\n"; - return 1; + }); + results.push_back(std::move(task)); + } + int ret = 0; + for (auto& result : results) { + int val = result.get(); + if (val != 0) { + ret = val; } } - return 0; + return ret; } + -- cgit v1.2.3-55-g6feb