From 65dd230959dbab99b52b99fd807534c254fb4ed9 Mon Sep 17 00:00:00 2001 From: Li Jin Date: Wed, 19 Jul 2017 11:05:45 +0800 Subject: add codes. --- MoonParser.xcodeproj/project.pbxproj | 10 +- MoonParser/ast.hpp | 2 - MoonParser/main.cpp | 1652 -------------------------------- MoonParser/moon_ast.cpp | 1718 ++++++---------------------------- MoonParser/moon_ast.h | 589 +++++++++++- MoonParser/moon_parser.cpp | 508 ++++++++++ MoonParser/moon_parser.h | 31 + 7 files changed, 1444 insertions(+), 3066 deletions(-) delete mode 100644 MoonParser/main.cpp create mode 100644 MoonParser/moon_parser.cpp create mode 100644 MoonParser/moon_parser.h diff --git a/MoonParser.xcodeproj/project.pbxproj b/MoonParser.xcodeproj/project.pbxproj index 782ec62..fe4dd22 100644 --- a/MoonParser.xcodeproj/project.pbxproj +++ b/MoonParser.xcodeproj/project.pbxproj @@ -9,7 +9,7 @@ /* Begin PBXBuildFile section */ 3C3B1C601F1EF0AB0052A206 /* moon_ast.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C3B1C5E1F1EF0AB0052A206 /* moon_ast.cpp */; }; 3C6FFA331F16F97400541BCA /* ast.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C6FFA2D1F16F97400541BCA /* ast.cpp */; }; - 3C6FFA341F16F97400541BCA /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C6FFA2F1F16F97400541BCA /* main.cpp */; }; + 3C6FFA341F16F97400541BCA /* moon_parser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C6FFA2F1F16F97400541BCA /* moon_parser.cpp */; }; 3C6FFA351F16F97400541BCA /* parser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C6FFA301F16F97400541BCA /* parser.cpp */; }; /* End PBXBuildFile section */ @@ -29,9 +29,10 @@ 3C0F0F6C1EF3781E000EADDB /* MoonParser */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = MoonParser; sourceTree = BUILT_PRODUCTS_DIR; }; 3C3B1C5E1F1EF0AB0052A206 /* moon_ast.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = moon_ast.cpp; sourceTree = ""; }; 3C3B1C5F1F1EF0AB0052A206 /* moon_ast.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = moon_ast.h; sourceTree = ""; }; + 3C3B1C611F1EFC810052A206 /* moon_parser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = moon_parser.h; sourceTree = ""; }; 3C6FFA2D1F16F97400541BCA /* ast.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ast.cpp; sourceTree = ""; }; 3C6FFA2E1F16F97400541BCA /* ast.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = ast.hpp; sourceTree = ""; }; - 3C6FFA2F1F16F97400541BCA /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; }; + 3C6FFA2F1F16F97400541BCA /* moon_parser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = moon_parser.cpp; sourceTree = ""; }; 3C6FFA301F16F97400541BCA /* parser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = parser.cpp; sourceTree = ""; }; 3C6FFA311F16F97400541BCA /* parser.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = parser.hpp; sourceTree = ""; }; 3C6FFA321F16F97400541BCA /* parserlib.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = parserlib.hpp; sourceTree = ""; }; @@ -53,7 +54,8 @@ children = ( 3C6FFA2D1F16F97400541BCA /* ast.cpp */, 3C6FFA2E1F16F97400541BCA /* ast.hpp */, - 3C6FFA2F1F16F97400541BCA /* main.cpp */, + 3C6FFA2F1F16F97400541BCA /* moon_parser.cpp */, + 3C3B1C611F1EFC810052A206 /* moon_parser.h */, 3C3B1C5E1F1EF0AB0052A206 /* moon_ast.cpp */, 3C3B1C5F1F1EF0AB0052A206 /* moon_ast.h */, 3C6FFA301F16F97400541BCA /* parser.cpp */, @@ -136,7 +138,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 3C6FFA341F16F97400541BCA /* main.cpp in Sources */, + 3C6FFA341F16F97400541BCA /* moon_parser.cpp in Sources */, 3C3B1C601F1EF0AB0052A206 /* moon_ast.cpp in Sources */, 3C6FFA351F16F97400541BCA /* parser.cpp in Sources */, 3C6FFA331F16F97400541BCA /* ast.cpp in Sources */, diff --git a/MoonParser/ast.hpp b/MoonParser/ast.hpp index a9c2db7..1b40e1b 100644 --- a/MoonParser/ast.hpp +++ b/MoonParser/ast.hpp @@ -69,8 +69,6 @@ public: virtual void visit(void* user_data) {} virtual int get_type() { return ast_type(); } - - virtual ast_node* get_flattened() { return this; } private: //parent ast_node *m_parent; diff --git a/MoonParser/main.cpp b/MoonParser/main.cpp deleted file mode 100644 index d0ef5c8..0000000 --- a/MoonParser/main.cpp +++ /dev/null @@ -1,1652 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include "parserlib.hpp" -using namespace parserlib; - -template -struct deletable_facet : Facet -{ - template - deletable_facet(Args&& ...args): Facet(std::forward(args)...) {} - ~deletable_facet() {} -}; -typedef std::wstring_convert>, char32_t> Converter; - -static inline std::string& trim(std::string& s) -{ - s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char ch) - { - return !std::isspace(ch); - })); - s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) - { - return !std::isspace(ch); - }).base(), s.end()); - return s; -} - -#define p(expr) user(expr, [](const item_t& item) \ -{ \ - stringstream stream; \ - for (input_it i = item.begin; i != item.end; ++i) stream << static_cast(*i); \ - cout << #expr << ": [" << stream.str() << "]\n"; \ - return true; \ -}) - -struct State -{ - State() - { - indents.push(0); - stringOpen = -1; - } - std::stringstream buffer; - size_t stringOpen; - std::stack indents; - std::stack doStack; - std::unordered_set keywords = { - "and", "while", "else", "using", "continue", - "local", "not", "then", "return", "from", - "extends", "for", "do", "or", "export", - "class", "in", "unless", "when", "elseif", - "switch", "break", "if", "with", "import" - }; -}; - -class Data -{ -public: - Data() - { - indent = 0; - callerStack.push(false); - } - - Converter conv; - std::stringstream temp; - std::stringstream buffer; - std::vector lineTable; - std::stack callerStack; - std::stack withStack; - - void beginLine(int line = -1) - { - for (int i = 0; i < indent; i++) - { - buffer << '\t'; - } - lineTable.push_back(line == -1 ? lineTable.back() : line); - } - - void endLine() - { - buffer << '\n'; - } - - int indent; - struct Scope - { - Scope() - { - localObjIndex = 0; - localFnIndex = 0; - localBaseIndex = 0; - localWithIndex = 0; - } - int localObjIndex; - int localFnIndex; - int localBaseIndex; - int localWithIndex; - std::vector locals; - }; - - std::string getNewLocalObj() - { - temp << "_obj_" << scope().localObjIndex; - scope().localObjIndex++; - std::string local = temp.str(); - temp.str(""); - temp.clear(); - return local; - } - - std::string getNewLocalFn() - { - temp << "_fn_" << scope().localObjIndex; - scope().localFnIndex++; - std::string local = temp.str(); - temp.str(""); - temp.clear(); - return local; - } - - std::string getNewLocalBase() - { - temp << "_base_" << scope().localBaseIndex; - scope().localBaseIndex++; - std::string local = temp.str(); - temp.str(""); - temp.clear(); - return local; - } - - bool isLocal(const std::string& var) - { - return _localVars.find(var) != _localVars.end(); - } - - void putLocal(const std::string& var) - { - if (_localVars.find(var) == _localVars.end()) - { - _localVars.insert(var); - _scopeStack.top().locals.push_back(var); - } - } - - void pushScope() - { - int lastWithIndex = scope().localWithIndex; - _scopeStack.emplace(); - scope().localWithIndex = lastWithIndex + 1; - indent++; - } - - Scope& scope() - { - return _scopeStack.top(); - } - - void popScope() - { - const auto& scope = _scopeStack.top(); - for (const auto& var : scope.locals) - { - _localVars.erase(var); - } - _scopeStack.pop(); - indent--; - } -private: - std::unordered_set _localVars; - std::stack _scopeStack; -}; - -rule Any = any(); -rule plain_space = *set(" \t"); -rule Break = nl(-expr('\r') >> '\n'); -rule White = *(set(" \t") | Break); -rule Stop = Break | eof(); -rule Comment = "--" >> *(not_(set("\r\n")) >> Any) >> and_(Stop); -rule Indent = *set(" \t"); -rule Space = plain_space >> -Comment; -rule SomeSpace = +set(" \t") >> -Comment; -rule SpaceBreak = Space >> Break; -rule EmptyLine = SpaceBreak; -rule AlphaNum = range('a', 'z') | range('A', 'Z') | range('0', '9') | '_'; -rule _Name = (range('a', 'z') | range('A', 'Z') | '_') >> *AlphaNum; -rule SpaceName = Space >> _Name; -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") - ) | ( - ( - (+range('0', '9') >> -('.' >> +range('0', '9'))) | - ('.' >> +range('0', '9')) - ) >> -(set("eE") >> -expr('-') >> +range('0', '9')) - ); -rule Num = Space >> _Num; -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)) -#define opWord(str) (Space >> str >> not_(AlphaNum)) -#define op(str) (Space >> str) - -rule Name = user(SpaceName, [](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); - std::string name; - st->buffer >> name; - st->buffer.str(""); - st->buffer.clear(); - auto it = st->keywords.find(name); - return it == st->keywords.end(); -}); - -rule self = expr('@'); -rule self_name = '@' >> _Name; -rule self_class = expr("@@"); -rule self_class_name = "@@" >> _Name; - -rule SelfName = Space >> (self_class_name | self_class | self_name | self); -rule KeyName = SelfName | Space >> _Name; -rule VarArg = Space >> "..."; - -rule check_indent = user(Indent, [](const item_t& item) -{ - int indent = 0; - for (input_it i = item.begin; i != item.end; ++i) - { - switch (*i) - { - case ' ': indent++; break; - case '\t': indent += 4; break; - } - } - State* st = reinterpret_cast(item.user_data); - return st->indents.top() == indent; -}); -rule CheckIndent = and_(check_indent); - -rule advance = user(Indent, [](const item_t& item) -{ - int indent = 0; - for (input_it i = item.begin; i != item.end; ++i) - { - switch (*i) - { - case ' ': indent++; break; - case '\t': indent += 4; break; - } - } - State* st = reinterpret_cast(item.user_data); - int top = st->indents.top(); - if (top != -1 && indent > top) - { - st->indents.push(indent); - return true; - } - return false; -}); -rule Advance = and_(advance); - -rule push_indent = user(Indent, [](const item_t& item) -{ - int indent = 0; - for (input_it i = item.begin; i != item.end; ++i) - { - switch (*i) - { - case ' ': indent++; break; - case '\t': indent += 4; break; - } - } - State* st = reinterpret_cast(item.user_data); - st->indents.push(indent); - return true; -}); -rule PushIndent = and_(push_indent); - -rule PreventIndent = user(true_(), [](const item_t& item) -{ - State* st = reinterpret_cast(item.user_data); - st->indents.push(-1); - return true; -}); - -rule PopIndent = user(true_(), [](const item_t& item) -{ - State* st = reinterpret_cast(item.user_data); - st->indents.pop(); - return true; -}); - -extern rule Block; - -rule InBlock = Advance >> Block >> PopIndent; - -extern rule NameList; - -rule local_flag = op('*') | op('^'); -rule Local = key("local") >> (local_flag | NameList); - -rule colon_import_name = sym('\\') >> Name; -rule ImportName = colon_import_name | Name; -rule ImportNameList = Seperator >> *SpaceBreak >> ImportName >> *((+SpaceBreak | sym(',') >> *SpaceBreak) >> ImportName); - -extern rule Exp; - -rule Import = key("import") >> ImportNameList >> *SpaceBreak >> key("from") >> Exp; -rule BreakLoop = key("break") | key("continue"); - -extern rule ExpListLow, ExpList, Assign; - -rule Return = key("return") >> -ExpListLow; -rule WithExp = ExpList >> -Assign; - -extern rule DisableDo, PopDo, Body; - -rule With = key("with") >> DisableDo >> ensure(WithExp, PopDo) >> -key("do") >> Body; -rule SwitchCase = key("when") >> ExpList >> -key("then") >> Body; -rule SwitchElse = key("else") >> Body; - -rule SwitchBlock = *EmptyLine >> - Advance >> Seperator >> - SwitchCase >> - *(+Break >> SwitchCase) >> - -(+Break >> SwitchElse) >> - PopIndent; - -rule Switch = key("switch") >> - DisableDo >> ensure(Exp, PopDo) >> - -key("do") >> -Space >> Break >> SwitchBlock; - -rule IfCond = Exp >> -Assign; -rule IfElseIf = -(Break >> *EmptyLine >> CheckIndent) >> key("elseif") >> IfCond >> -key("then") >> Body; -rule IfElse = -(Break >> *EmptyLine >> CheckIndent) >> key("else") >> Body; -rule If = key("if") >> IfCond >> -key("then") >> Body >> Seperator >> *IfElseIf >> -IfElse; -rule Unless = key("unless") >> IfCond >> -key("then") >> Body >> Seperator >> *IfElseIf >> -IfElse; - -rule While = key("while") >> DisableDo >> ensure(Exp, PopDo) >> -key("do") >> Body; - -rule for_step_value = sym(',') >> Exp; -rule for_args = Name >> sym('=') >> Exp >> sym(',') >> Exp >> -for_step_value; - -rule For = key("for") >> DisableDo >> - ensure(for_args, PopDo) >> - -key("do") >> Body; - -extern rule AssignableNameList; - -rule for_in = sym('*') >> Exp | ExpList; - -rule ForEach = key("for") >> AssignableNameList >> key("in") >> - DisableDo >> ensure(for_in, PopDo) >> - -key("do") >> Body; - -rule Do = user(key("do") >> Body, [](const item_t& item) -{ - State* st = reinterpret_cast(item.user_data); - return st->doStack.empty() || st->doStack.top(); -}); - -rule DisableDo = user(true_(), [](const item_t& item) -{ - State* st = reinterpret_cast(item.user_data); - st->doStack.push(false); - return true; -}); - -rule PopDo = user(true_(), [](const item_t& item) -{ - State* st = reinterpret_cast(item.user_data); - st->doStack.pop(); - return true; -}); - -extern rule CompInner; - -rule Comprehension = sym('[') >> Exp >> CompInner >> sym(']'); -rule comp_value = sym(',') >> Exp; -rule TblComprehension = sym('{') >> (Exp >> -comp_value) >> CompInner >> sym('}'); - -extern rule CompForEach, CompFor, CompClause; - -rule CompInner = (CompForEach | CompFor) >> Seperator >> *CompClause; -rule star_exp = sym('*') >> Exp; -rule CompForEach = key("for") >> AssignableNameList >> key("in") >> (star_exp | Exp); -rule CompFor = key("for") >> Name >> sym('=') >> Exp >> sym(',') >> Exp >> -for_step_value; -rule CompClause = CompFor | CompForEach | key("when") >> Exp; - -extern rule TableBlock; - -rule Assign = sym('=') >> (With | If | Switch | TableBlock | ExpListLow); - -rule update_op = - sym("..=") | - sym("+=") | - sym("-=") | - sym("*=") | - sym("/=") | - sym("%=") | - sym("or=") | - sym("and=") | - sym("&=") | - sym("|=") | - sym(">>=") | - sym("<<="); - -rule Update = update_op >> Exp; - -rule CharOperators = Space >> set("+-*/%^><|&"); -rule WordOperators = - opWord("or") | - opWord("and") | - op("<=") | - op(">=") | - op("~=") | - op("!=") | - op("==") | - op("..") | - op("<<") | - op(">>") | - op("//"); - -rule BinaryOperator = (WordOperators | CharOperators) >> *SpaceBreak; - -extern rule Chain; - -rule Assignable = Chain | Name | SelfName; - -extern rule Value; - -rule exp_op_value = BinaryOperator >> Value; -rule Exp = Value >> *exp_op_value; - -extern rule Callable, InvokeArgs; - -rule ChainValue = (Chain | Callable) >> -InvokeArgs; - -extern rule KeyValue, String, SimpleValue; - -rule simple_table = Seperator >> KeyValue >> *(sym(',') >> KeyValue); -rule Value = SimpleValue | simple_table | ChainValue | String; - -extern rule LuaString; - -rule single_string_inner = expr("\\'") | "\\\\" | not_(expr('\'')) >> Any; -rule SingleString = symx('\'') >> *single_string_inner >> sym('\''); -rule interp = symx("#{") >> Exp >> sym('}'); -rule double_string_plain = expr("\\\"") | "\\\\" | not_(expr('"')) >> Any; -rule double_string_inner = +(not_(interp) >> double_string_plain); -rule double_string_content = double_string_inner | interp; -rule DoubleString = symx('"') >> Seperator >> *double_string_content >> sym('"'); -rule String = Space >> (DoubleString | SingleString | LuaString); - -rule lua_string_open = '[' >> *expr('=') >> '['; -rule lua_string_close = ']' >> *expr('=') >> ']'; - -rule LuaStringOpen = user(lua_string_open, [](const item_t& item) -{ - size_t count = std::distance(item.begin, item.end); - State* st = reinterpret_cast(item.user_data); - st->stringOpen = count; - return true; -}); - -rule LuaStringClose = user(lua_string_close, [](const item_t& item) -{ - size_t count = std::distance(item.begin, item.end); - State* st = reinterpret_cast(item.user_data); - return st->stringOpen == count; -}); - -rule LuaStringContent = *(not_(LuaStringClose) >> (Break | Any)); - -rule LuaString = user(LuaStringOpen >> -Break >> LuaStringContent >> LuaStringClose, [](const item_t& item) -{ - State* st = reinterpret_cast(item.user_data); - st->stringOpen = -1; - return true; -}); - -rule Parens = sym('(') >> *SpaceBreak >> Exp >> *SpaceBreak >> sym(')'); -rule Callable = Name | SelfName | VarArg | Parens; -rule FnArgsExpList = Exp >> *((Break | sym(',')) >> White >> Exp); - -rule FnArgs = Seperator >> -( - ( - symx('(') >> *SpaceBreak >> -FnArgsExpList >> *SpaceBreak >> sym(')') - ) | ( - sym('!') >> not_(expr('=')) - ) -); - -extern rule ChainItems, DotChainItem, ColonChain; - -rule chain_call = (Callable | String) >> ChainItems; -rule chain_item = not_(set(".\\")) >> ChainItems; -rule chain_dot_chain = DotChainItem >> -ChainItems; - -rule Chain = - chain_call | - chain_item | - Space >> (chain_dot_chain | ColonChain); - -extern rule ChainItem; - -rule chain_with_colon = +ChainItem >> -ColonChain; -rule ChainItems = Seperator >> (chain_with_colon | ColonChain); - -extern rule Invoke, Slice; - -rule Index = symx('[') >> Exp >> sym(']'); -rule ChainItem = Invoke | DotChainItem | Slice | Index; -rule DotChainItem = symx('.') >> _Name; -rule ColonChainItem = symx('\\') >> _Name; -rule invoke_chain = Invoke >> -ChainItems; -rule ColonChain = ColonChainItem >> -invoke_chain; - -rule default_value = true_(); -rule Slice = - symx('[') >> - (Exp | default_value) >> - sym(',') >> - (Exp | default_value) >> - (sym(',') >> Exp | default_value) >> - sym(']'); - -rule Invoke = - FnArgs | - SingleString | - DoubleString | - and_(expr('[')) >> LuaString; - -extern rule TableValueList, TableLitLine; - -rule TableValue = KeyValue | Exp; - -rule table_lit_lines = SpaceBreak >> TableLitLine >> *(-sym(',') >> SpaceBreak >> TableLitLine) >> -sym(','); - -rule TableLit = - sym('{') >> Seperator >> - -TableValueList >> - -sym(',') >> - -table_lit_lines >> - White >> sym('}'); - -rule TableValueList = TableValue >> *(sym(',') >> TableValue); - -rule TableLitLine = -( - PushIndent >> (TableValueList >> PopIndent | PopIndent) -) | ( - Space -); - -extern rule KeyValueLine; - -rule TableBlockInner = Seperator >> KeyValueLine >> *(+(SpaceBreak) >> KeyValueLine); -rule TableBlock = +(SpaceBreak) >> Advance >> ensure(TableBlockInner, PopIndent); - -extern rule Statement; - -rule class_member_list = Seperator >> KeyValue >> *(sym(',') >> KeyValue); -rule ClassLine = CheckIndent >> (class_member_list | Statement | Exp) >> -sym(','); -rule ClassBlock = +(SpaceBreak) >> Advance >>Seperator >> ClassLine >> *(+(SpaceBreak) >> ClassLine) >> PopIndent; - -rule ClassDecl = - key("class") >> not_(expr(':')) >> - -Assignable >> - -(key("extends") >> PreventIndent >> ensure(Exp, PopIndent)) >> - -ClassBlock; - -rule export_values = NameList >> -(sym('=') >> ExpListLow); -rule export_op = op('*') | op('^'); -rule Export = key("export") >> (ClassDecl | export_op | export_values); - -rule variable_pair = sym(':') >> not_(SomeSpace) >> Name; - -rule normal_pair = -( - KeyName | - sym('[') >> Exp >> sym(']') | - Space >> DoubleString | - Space >> SingleString -) >> -symx(':') >> -(Exp | TableBlock | +(SpaceBreak) >> Exp); - -rule KeyValue = variable_pair | normal_pair; - -rule KeyValueList = KeyValue >> *(sym(',') >> KeyValue); -rule KeyValueLine = CheckIndent >> KeyValueList >> -sym(','); - -rule FnArgDef = (Name | SelfName) >> -(sym('=') >> Exp); - -rule FnArgDefList = Seperator >> -( - ( - FnArgDef >> - *((sym(',') | Break) >> White >> FnArgDef) >> - -((sym(',') | Break) >> White >> VarArg) - ) | ( - VarArg - ) -); - -rule outer_var_shadow = key("using") >> (NameList | Space >> expr("nil")); - -rule FnArgsDef = sym('(') >> White >> -FnArgDefList >> -outer_var_shadow >> White >> sym(')'); -rule fn_arrow = sym("->") | sym("=>"); -rule FunLit = -FnArgsDef >> fn_arrow >> -Body; - -rule NameList = Seperator >> Name >> *(sym(',') >> Name); -rule NameOrDestructure = Name | TableLit; -rule AssignableNameList = Seperator >> NameOrDestructure >> *(sym(',') >> NameOrDestructure); - -rule ExpList = Seperator >> Exp >> *(sym(',') >> Exp); -rule ExpListLow = Seperator >> Exp >> *((sym(',') | sym(';')) >> Exp); - -rule ArgLine = CheckIndent >> Exp >> *(sym(',') >> Exp); -rule ArgBlock = Seperator >> ArgLine >> *(sym(',') >> SpaceBreak >> ArgLine) >> PopIndent; - -rule invoke_args_with_table = - sym(',') >> - ( - TableBlock | - SpaceBreak >> Advance >> ArgBlock >> -TableBlock - ); - -rule InvokeArgs = - not_(expr('-')) >> - ( - ExpList >> -(invoke_args_with_table | TableBlock) | - TableBlock - ); - -rule const_value = key("nil") | key("true") | key("false"); -rule minus_exp = sym('-') >> not_(SomeSpace) >> Exp; -rule sharp_exp = sym('#') >> Exp; -rule tilde_exp = sym('~') >> Exp; -rule not_exp = key("not") >> Exp; -rule unary_exp = minus_exp | sharp_exp | tilde_exp | not_exp; - -rule SimpleValue = - const_value | - If | Unless | Switch | With | ClassDecl | ForEach | For | While | Do | - unary_exp | - TblComprehension | TableLit | Comprehension | FunLit | Num; - -rule Assignment = ExpList >> (Update | Assign); - -rule if_else_line = key("if") >> Exp >> (key("else") >> Exp | default_value); -rule unless_line = key("unless") >> Exp; - -rule statement_appendix = (if_else_line | unless_line | CompInner) >> Space; -rule Statement = -( - Import | While | With | For | ForEach | - Switch | Return | Local | Export | BreakLoop | - Assignment | ExpList -) >> 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 BlockEnd = Block >> eof(); - -class AstLeaf : public ast_node -{ -public: - const std::string& getValue() - { - if (_value.empty()) - { - for (auto it = m_begin.m_it; it != m_end.m_it; ++it) - { - char ch = static_cast(*it); - _value.append(&ch, 1); - } - return trim(_value); - } - return _value; - } -private: - std::string _value; -}; - -#define AST_LEAF(type) \ -class type##_t : public AstLeaf \ -{ \ -public: \ - virtual int get_type() override { return ast_type(); } - -#define AST_NODE(type) \ -class type##_t : public ast_container \ -{ \ -public: \ - virtual int get_type() override { return ast_type(); } - -#define AST_END(type) \ -}; \ -ast __##type##_t(type); - -AST_LEAF(Num) - virtual void visit(void* ud) override - { - Data* data = static_cast(ud); - std::string str = data->conv.to_bytes(&*m_begin.m_it, &*m_end.m_it); - data->buffer << trim(str); - } -AST_END(Num) - -AST_LEAF(_Name) - virtual void visit(void* ud) override - { - Data* data = static_cast(ud); - data->buffer << getValue(); - } -AST_END(_Name) - -AST_NODE(Name) - ast_ptr<_Name_t> name; - virtual void visit(void* ud) override - { - name->visit(ud); - } -AST_END(Name) - -AST_LEAF(self) - virtual void visit(void* ud) override - { - Data* data = static_cast(ud); - data->buffer << "self"; - } -AST_END(self) - -AST_NODE(self_name) - ast_ptr<_Name_t> name; - virtual void visit(void* ud) override - { - Data* data = static_cast(ud); - data->buffer << (data->callerStack.top() ? "self:" : "self."); - name->visit(ud); - } -AST_END(self_name) - -AST_LEAF(self_class) - virtual void visit(void* ud) override - { - Data* data = static_cast(ud); - data->buffer << "self.__class"; - } -AST_END(self_class) - -AST_NODE(self_class_name) - ast_ptr<_Name_t> name; - virtual void visit(void* ud) override - { - Data* data = static_cast(ud); - data->buffer << (data->callerStack.top() ? "self.__class:" : "self.__class."); - name->visit(ud); - } -AST_END(self_class_name) - -AST_NODE(SelfName) - ast_ptr name; // self_class_name_t | self_class_t | self_name_t | self_t - virtual void visit(void* ud) override - { - name->visit(ud); - } -AST_END(SelfName) - -AST_NODE(KeyName) - ast_ptr name; // SelfName_t | _Name_t - virtual void visit(void* ud) override - { - name->visit(ud); - } -AST_END(KeyName) - -AST_LEAF(VarArg) - virtual void visit(void* ud) override - { - Data* data = static_cast(ud); - data->buffer << "..."; - } -AST_END(VarArg) - -AST_LEAF(local_flag) -AST_END(local_flag) - -AST_LEAF(Seperator) -AST_END(Seperator) - -AST_NODE(NameList) - ast_ptr sep; - ast_list names; - virtual void visit(void* ud) override - { - Data* data = static_cast(ud); - auto it = names.objects().begin(); - Name_t* name = *it; - name->visit(ud); - ++it; - for (; it != names.objects().end(); ++it) - { - name = *it; - data->buffer << ", "; - name->visit(ud); - } - } -AST_END(NameList) - -AST_NODE(Local) - ast_ptr name; // local_flag_t | NameList_t -AST_END(Local) - -AST_NODE(colon_import_name) - ast_ptr name; -AST_END(colon_import_name) - -class Exp_t; - -AST_NODE(ImportName) - ast_ptr name; // colon_import_name_t | Name_t -AST_END(ImportName) - -AST_NODE(Import) - ast_ptr sep; - ast_list names; - ast_ptr exp; - virtual void visit(void* ud) override - { - Data* data = static_cast(ud); - std::vector> nameItems; - nameItems.reserve(names.objects().size()); - for (ImportName_t* importName : names.objects()) - { - if (Name_t* name = ast_cast(importName->name)) - { - nameItems.push_back(std::make_tuple(&name->name->getValue(), false)); - } - else - { - colon_import_name_t* colonName = ast_cast(importName->name); - nameItems.push_back(std::make_tuple(&colonName->name->name->getValue(), true)); - } - } - data->buffer << "local "; - for (const auto& item : nameItems) - { - data->buffer << *std::get<0>(item); - if (&item != &nameItems.back()) - { - data->buffer << ", "; - } - } - data->endLine(); - - data->beginLine(); - data->pushScope(); - data->buffer << "do"; - data->endLine(); - - std::string fromObj = data->getNewLocalObj(); - - data->beginLine(); - data->buffer << "local " << fromObj << " = "; - ((ast_node*)exp.get())->visit(ud); - data->endLine(); - - data->beginLine(); - for (const auto& item : nameItems) - { - data->buffer << *std::get<0>(item); - if (&item != &nameItems.back()) - { - data->buffer << ", "; - } - } - data->buffer << " = "; - for (const auto& item : nameItems) - { - if (std::get<1>(item)) - { - data->pushScope(); - data->buffer << "(function()"; - data->endLine(); - - std::string varBase = data->getNewLocalBase(); - - data->beginLine(); - data->buffer << "local " << varBase << " = " << fromObj; - data->endLine(); - - std::string varFn = data->getNewLocalFn(); - - data->beginLine(); - data->buffer << "local " << varFn << " = " << varBase << '.' << *std::get<0>(item); - data->endLine(); - - data->beginLine(); - data->buffer << "return function(...)"; - data->endLine(); - - data->beginLine(); - data->pushScope(); - data->buffer << varFn << '(' << varBase << ", ...)"; - data->endLine(); - - data->beginLine(); - data->buffer << "end"; - data->popScope(); - data->endLine(); - - data->beginLine(); - data->buffer << "end)()"; - data->popScope(); - } - else - { - data->buffer << fromObj << '.' << *std::get<0>(item); - } - if (&item != &nameItems.back()) - { - data->buffer << ", "; - } - } - data->endLine(); - - data->beginLine(); - data->buffer << "end"; - data->popScope(); - } -AST_END(Import) - -AST_NODE(ExpListLow) - ast_ptr sep; - ast_list exprs; - virtual void visit(void* ud) override - { - Data* data = static_cast(ud); - for (Exp_t* expr : exprs.objects()) - { - ((ast_node*)expr)->visit(ud); - if (expr != exprs.objects().back()) - { - data->buffer << ", "; - } - } - } -AST_END(ExpListLow) - -AST_NODE(ExpList) - ast_ptr sep; - ast_list exprs; - virtual void visit(void* ud) override - { - Data* data = static_cast(ud); - for (Exp_t* expr : exprs.objects()) - { - ((ast_node*)expr)->visit(ud); - if (expr != exprs.objects().back()) - { - data->buffer << ", "; - } - } - } -AST_END(ExpList) - -AST_NODE(Return) - ast_ptr valueList; - virtual void visit(void* ud) override - { - Data* data = static_cast(ud); - data->buffer << "return"; - if (valueList && !valueList->exprs.objects().empty()) - { - data->buffer << ' '; - valueList->visit(ud); - } - } -AST_END(Return) - -class Assign_t; -class Body_t; - -AST_NODE(With) - ast_ptr valueList; - ast_ptr assigns; - ast_ptr body; - /* - (function() - do - local _with_0 = Something() - _with_0:write("hello world") - return _with_0 - end - end)() - */ - virtual void visit(void* ud) override - { - } -AST_END(With) - -AST_NODE(SwitchCase) - ast_ptr valueList; - ast_ptr body; -AST_END(SwitchCase) - -AST_NODE(Switch) - ast_ptr target; - ast_ptr sep; - ast_list branches; - ast_ptr lastBranch; -AST_END(Switch) - -AST_NODE(IfCond) - ast_ptr condition; - ast_ptr assign; -AST_END(IfCond) - -AST_NODE(IfElseIf) - ast_ptr condition; - ast_ptr body; -AST_END(IfElseIf) - -AST_NODE(If) - ast_ptr firstCondition; - ast_ptr firstBody; - ast_ptr sep; - ast_list branches; - ast_ptr lastBranch; -AST_END(If) - -AST_NODE(Unless) - ast_ptr firstCondition; - ast_ptr firstBody; - ast_ptr sep; - ast_list branches; - ast_ptr lastBranch; -AST_END(Unless) - -AST_NODE(While) - ast_ptr condition; - ast_ptr body; -AST_END(While) - -AST_NODE(for_step_value) - ast_ptr value; -AST_END(for_step_value) - -AST_NODE(For) - ast_ptr varName; - ast_ptr startValue; - ast_ptr stopValue; - ast_ptr stepValue; - ast_ptr body; -AST_END(For) - -class AssignableNameList_t; - -AST_NODE(ForEach) - ast_ptr nameList; - ast_ptr loopValue; // Exp_t | ExpList_t - ast_ptr body; -AST_END(ForEach) - -AST_NODE(Do) - ast_ptr body; -AST_END(Do) - -class CompInner_t; - -AST_NODE(Comprehension) - ast_ptr value; - ast_ptr forLoop; -AST_END(Comprehension) - -AST_NODE(comp_value) - ast_ptr value; -AST_END(comp_value) - -AST_NODE(TblComprehension) - ast_ptr key; - ast_ptr value; - ast_ptr forLoop; -AST_END(TblComprehension) - -AST_NODE(star_exp) - ast_ptr value; -AST_END(star_exp) - -AST_NODE(CompForEach) - ast_ptr nameList; - ast_ptr loopValue; // star_exp_t | Exp_t -AST_END(CompForEach) - -AST_NODE(CompFor) - ast_ptr varName; - ast_ptr startValue; - ast_ptr stopValue; - ast_ptr stepValue; -AST_END(CompFor) - -AST_NODE(CompClause) - ast_ptr nestExp; // CompFor_t | CompForEach_t | Exp_t -AST_END(CompClause) - -AST_NODE(CompInner) - ast_ptr compFor; // CompFor_t | CompForEach_t - ast_ptr sep; - ast_list clauses; -AST_END(CompInner) - -class TableBlock_t; - -AST_NODE(Assign) - ast_ptr value; // With_t | If_t | Switch_t | TableBlock_t | ExpListLow_t -AST_END(Assign) - -AST_LEAF(update_op) -AST_END(update_op) - -AST_NODE(Update) - ast_ptr op; - ast_ptr value; -AST_END(Update) - -AST_LEAF(BinaryOperator) -AST_END(BinaryOperator) - -class Chain_t; - -AST_NODE(Assignable) - ast_ptr item; // Chain_t | Name_t | SelfName_t -AST_END(Assignable) - -class Value_t; - -AST_NODE(exp_op_value) - ast_ptr op; - ast_ptr value; -AST_END(exp_op_value) - -AST_NODE(Exp) - ast_ptr value; - ast_list opValues; -AST_END(Exp) - -AST_NODE(Callable) - ast_ptr item; // Name_t | SelfName_t | VarArg_t | Parens_t -AST_END(Callable) - -class InvokeArgs_t; - -AST_NODE(ChainValue) - ast_ptr caller; // Chain_t | Callable_t - ast_ptr arguments; - - virtual void visit(void* ud) override - { - - } -AST_END(ChainValue) - -class KeyValue_t; - -AST_NODE(simple_table) - ast_ptr sep; - ast_list pairs; -AST_END(simple_table) - -class String_t; - -AST_NODE(SimpleValue) - ast_ptr value; /* - const_value_t | - If_t | Unless_t | Switch_t | With_t | ClassDecl_t | ForEach_t | For_t | While_t | Do_t | - unary_exp_t | - TblComprehension_t | TableLit_t | Comprehension_t | FunLit_t | Num_t; - */ -AST_END(SimpleValue) - -AST_NODE(Chain) - ast_ptr item; // chain_call_t | chain_item_t | chain_dot_chain_t | ColonChain_t -AST_END(Chain) - -AST_NODE(Value) - ast_ptr item; // SimpleValue_t | simple_table_t | ChainValue_t | String_t - virtual ast_node* get_flattened() override - { - if (SimpleValue_t* simpleValue = ast_cast(item)) - { - return simpleValue->value; - } - else if (simple_table_t* simple_table = ast_cast(item)) - { - return simple_table; - } - else if (ChainValue_t* chainValue = ast_cast(item)) - { - if (chainValue->arguments) - { - return chainValue; - } - else - { - if (Chain_t* chain = ast_cast(chainValue->caller)) - { - return chain->item; - } - else if (Callable_t* callable = ast_cast(chainValue->caller)) - { - return callable->item; - } - } - } - return item; - } -AST_END(Value) - -AST_LEAF(LuaString) -AST_END(LuaString) - -AST_LEAF(SingleString) -AST_END(SingleString) - -AST_LEAF(double_string_inner) -AST_END(double_string_inner) - -AST_NODE(double_string_content) - ast_ptr content; // double_string_inner_t | Exp_t -AST_END(double_string_content) - -AST_NODE(DoubleString) - ast_ptr sep; - ast_list segments; -AST_END(DoubleString) - -AST_NODE(String) - ast_ptr str; // DoubleString_t | SingleString_t | LuaString_t -AST_END(String) - -AST_NODE(Parens) - ast_ptr expr; -AST_END(Parens) - -AST_NODE(FnArgs) - ast_ptr sep; - ast_list args; -AST_END(FnArgs) - -class ChainItems_t; - -AST_NODE(chain_call) - ast_ptr caller; // Callable_t | String_t - ast_ptr chain; -AST_END(chain_call) - -AST_NODE(chain_item) - ast_ptr chain; -AST_END(chain_item) - -AST_NODE(DotChainItem) - ast_ptr<_Name_t> name; -AST_END(DotChainItem) - -AST_NODE(ColonChainItem) - ast_ptr<_Name_t> name; -AST_END(ColonChainItem) - -AST_NODE(chain_dot_chain) - ast_ptr caller; - ast_ptr chain; -AST_END(chain_dot_chain) - -class ColonChain_t; - -class Invoke_t; -class Slice_t; - -AST_NODE(ChainItem) - ast_ptr item; // Invoke_t | DotChainItem_t | Slice_t | [Exp_t] -AST_END(ChainItem) - -AST_NODE(ChainItems) - ast_ptr sep; - ast_list simpleChain; - ast_ptr colonChain; -AST_END(ChainItems) - -AST_NODE(invoke_chain) - ast_ptr invoke; - ast_ptr chain; -AST_END(invoke_chain) - -AST_NODE(ColonChain) - ast_ptr colonChain; - ast_ptr invokeChain; -AST_END(ColonChain) - -AST_LEAF(default_value) -AST_END(default_value) - -AST_NODE(Slice) - ast_ptr startValue; // Exp_t | default_value_t - ast_ptr stopValue; // Exp_t | default_value_t - ast_ptr stepValue; // Exp_t | default_value_t -AST_END(Slice) - -AST_NODE(Invoke) - ast_ptr argument; // FnArgs_t | SingleString_t | DoubleString_t | LuaString_t -AST_END(Invoke) - -class KeyValue_t; - -AST_NODE(TableValue) - ast_ptr value; // KeyValue_t | Exp_t -AST_END(TableValue) - -AST_NODE(TableLit) - ast_ptr sep; - ast_list values; -AST_END(TableLit) - -AST_NODE(TableBlock) - ast_ptr sep; - ast_list values; -AST_END(TableBlock) - -AST_NODE(class_member_list) - ast_ptr sep; - ast_list values; -AST_END(class_member_list) - -AST_NODE(ClassLine) - ast_ptr content; // class_member_list_t | Statement_t | Exp_t -AST_END(ClassLine) - -AST_NODE(ClassBlock) - ast_ptr sep; - ast_list lines; -AST_END(ClassBlock) - -AST_NODE(ClassDecl) - ast_ptr name; - ast_ptr extend; - ast_ptr body; -AST_END(ClassDecl) - -AST_NODE(export_values) - ast_ptr nameList; - ast_ptr valueList; -AST_END(export_values) - -AST_LEAF(export_op) -AST_END(export_op) - -AST_NODE(Export) - ast_ptr item; // ClassDecl_t | export_op_t | export_values_t -AST_END(Export) - -AST_NODE(variable_pair) - ast_ptr name; -AST_END(variable_pair) - -AST_NODE(normal_pair) - ast_ptr key; // KeyName_t | [Exp_t] | DoubleString_t | SingleString_t - ast_ptr value; // Exp_t | TableBlock_t -AST_END(normal_pair) - -AST_NODE(KeyValue) - ast_ptr item; // variable_pair_t | normal_pair_t -AST_END(KeyValue) - -AST_NODE(FnArgDef) - ast_ptr name; // Name_t | SelfName_t - ast_ptr defaultValue; -AST_END(FnArgDef) - -AST_NODE(FnArgDefList) - ast_ptr sep; - ast_list definitions; - ast_ptr varArg; -AST_END(FnArgDefList) - -AST_NODE(outer_var_shadow) - ast_ptr varList; -AST_END(outer_var_shadow) - -AST_NODE(FnArgsDef) - ast_ptr defList; - ast_ptr shadowOption; -AST_END(FnArgsDef) - -AST_LEAF(fn_arrow) -AST_END(fn_arrow) - -AST_NODE(FunLit) - ast_ptr argsDef; - ast_ptr arrow; - ast_ptr body; -AST_END(FunLit) - -AST_NODE(NameOrDestructure) - ast_ptr item; // Name_t | TableLit_t -AST_END(NameOrDestructure) - -AST_NODE(AssignableNameList) - ast_ptr sep; - ast_list items; -AST_END(AssignableNameList) - -AST_NODE(ArgBlock) - ast_ptr sep; - ast_list arguments; -AST_END(ArgBlock) - -AST_NODE(invoke_args_with_table) - ast_ptr argBlock; - ast_ptr tableBlock; -AST_END(invoke_args_with_table) - -AST_NODE(InvokeArgs) - ast_ptr argsList; - ast_ptr argsTableBlock; - ast_ptr tableBlock; -AST_END(InvokeArgs) - -AST_LEAF(const_value) -AST_END(const_value) - -AST_NODE(unary_exp) - ast_ptr item; -AST_END(unary_exp) - -AST_NODE(Assignment) - ast_ptr assignable; - ast_ptr target; // Update_t | Assign_t -AST_END(Assignment) - -AST_NODE(if_else_line) - ast_ptr condition; - ast_ptr elseExpr; // Exp_t | default_value_t -AST_END(if_else_line) - -AST_NODE(unless_line) - ast_ptr condition; -AST_END(unless_line) - -AST_NODE(statement_appendix) - ast_ptr item; // if_else_line_t | unless_line_t | CompInner_t -AST_END(statement_appendix) - -AST_LEAF(BreakLoop) -AST_END(BreakLoop) - -AST_NODE(Statement) - ast_ptr content; /* - Import_t | While_t | With_t | For_t | ForEach_t | - Switch_t | Return_t | Local_t | Export_t | BreakLoop_t | - Assignment_t | ExpList_t - */ - ast_ptr appendix; - - virtual void construct(ast_stack& st) override - { - std::wstring_convert>, char32_t> conv; - value = conv.to_bytes(&*m_begin.m_it, &*m_end.m_it); - ast_container::construct(st); - } - - virtual void visit(void* ud) override - { - std::cout << value << '\n'; - } - std::string value; -AST_END(Statement) - -class Block_t; - -AST_NODE(Body) - ast_ptr content; // Block | Statement - virtual void visit(void* ud) override - { - Data* data = static_cast(ud); - data->pushScope(); - content->visit(ud); - data->popScope(); - } -AST_END(Body) - -AST_NODE(Line) - ast_ptr statment; - int line; - - virtual void construct(ast_stack& st) override - { - ast_container::construct(st); - line = m_begin.m_line; - } - - virtual void visit(void* ud) override - { - if (statment) - { - std::cout << line << ": "; - statment->visit(ud); - } - } -AST_END(Line) - -AST_NODE(Block) - ast_ptr sep; - ast_list lines; - virtual void visit(void* ud) override - { - Data* data = static_cast(ud); - const auto& objs = lines.objects(); - for (auto it = objs.begin(); it != objs.end(); ++it) - { - Line_t* line = *it; - if (!line->statment) continue; - if (Local_t* local = ast_cast(line->statment->content)) - { - if (local_flag_t* local_flag = ast_cast(local->name)) - { - std::vector names; - for (auto cur = it; cur != objs.end(); ++cur) - { - Line_t* item = *cur; - if (!item->statment) continue; - if (Assignment_t* assignment = ast_cast(item->statment->content)) - { - for (Exp_t* expr : assignment->assignable->exprs.objects()) - { - if (ChainValue_t* chainValue = ast_cast(expr->value->item)) - if (Callable_t* callable = ast_cast(chainValue->caller)) - if (Name_t* name = ast_cast(callable->item)) - { - const std::string& value = name->name->getValue(); - if (local_flag->getValue() == "*") - { - names.push_back(&value); - } - else if (std::isupper(value[0])) - { - names.push_back(&value); - } - } - } - } - } - if (!names.empty()) - { - data->beginLine(line->m_begin.m_line); - data->buffer << "local "; - auto nameIt = names.begin(); - auto name = *(*nameIt); - data->putLocal(name); - data->buffer << name; - nameIt++; - for (; nameIt != names.end(); ++nameIt) - { - auto name = *(*nameIt); - data->putLocal(name); - data->buffer << ", "; - data->buffer << name; - } - data->endLine(); - } - } - else - { - NameList_t* nameList = static_cast(local->name.get()); - data->beginLine(line->m_begin.m_line); - data->buffer << "local "; - nameList->visit(ud); - for (Name_t* name : nameList->names.objects()) - { - data->putLocal(name->name->getValue()); - } - data->endLine(); - } - } - else - { - line->visit(ud); - } - } - } -AST_END(Block) - -AST_NODE(BlockEnd) - ast_ptr block; - virtual void visit(void* ud) override - { - Data* data = static_cast(ud); - data->pushScope(); - block->visit(ud); - data->popScope(); - } -AST_END(BlockEnd) - -int main() -{ - std::wstring_convert>, char32_t> conv; - std::string s = R"baddog(import \x, func, \memFunc from require "utils")baddog"; - input i = conv.from_bytes(s); - - error_list el; - Import_t* root = nullptr; - State st; - if (parse(i, Import, el, root, &st)) - { - std::cout << "matched!\n"; - Data data; - root->visit(&data); - } - else - { - std::cout << "not matched!\n"; - for (error_list::iterator it = el.begin(); it != el.end(); ++it) - { - const error& err = *it; - std::cout << "line " << err.m_begin.m_line << ", col " << err.m_begin.m_col << ": syntax error\n"; - } - } - system("pause"); - return 0; -} diff --git a/MoonParser/moon_ast.cpp b/MoonParser/moon_ast.cpp index 1595220..41d0c55 100644 --- a/MoonParser/moon_ast.cpp +++ b/MoonParser/moon_ast.cpp @@ -1,4 +1,3 @@ -#include #include #include #include @@ -6,58 +5,7 @@ #include #include #include -#include "parserlib.hpp" -using namespace parserlib; - -template -struct deletable_facet : Facet -{ - template - deletable_facet(Args&& ...args): Facet(std::forward(args)...) {} - ~deletable_facet() {} -}; -typedef std::wstring_convert>, char32_t> Converter; - -static inline std::string& trim(std::string& s) -{ - s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char ch) - { - return !std::isspace(ch); - })); - s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) - { - return !std::isspace(ch); - }).base(), s.end()); - return s; -} - -#define p(expr) user(expr, [](const item_t& item) \ -{ \ - stringstream stream; \ - for (input_it i = item.begin; i != item.end; ++i) stream << static_cast(*i); \ - cout << #expr << ": [" << stream.str() << "]\n"; \ - return true; \ -}) - -struct State -{ - State() - { - indents.push(0); - stringOpen = -1; - } - std::stringstream buffer; - size_t stringOpen; - std::stack indents; - std::stack doStack; - std::unordered_set keywords = { - "and", "while", "else", "using", "continue", - "local", "not", "then", "return", "from", - "extends", "for", "do", "or", "export", - "class", "in", "unless", "when", "elseif", - "switch", "break", "if", "with", "import" - }; -}; +#include "moon_ast.h" class Data { @@ -178,1457 +126,413 @@ private: std::stack _scopeStack; }; -rule Any = any(); -rule plain_space = *set(" \t"); -rule Break = nl(-expr('\r') >> '\n'); -rule White = *(set(" \t") | Break); -rule Stop = Break | eof(); -rule Comment = "--" >> *(not_(set("\r\n")) >> Any) >> and_(Stop); -rule Indent = *set(" \t"); -rule Space = plain_space >> -Comment; -rule SomeSpace = +set(" \t") >> -Comment; -rule SpaceBreak = Space >> Break; -rule EmptyLine = SpaceBreak; -rule AlphaNum = range('a', 'z') | range('A', 'Z') | range('0', '9') | '_'; -rule _Name = (range('a', 'z') | range('A', 'Z') | '_') >> *AlphaNum; -rule SpaceName = Space >> _Name; -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") - ) | ( - ( - (+range('0', '9') >> -('.' >> +range('0', '9'))) | - ('.' >> +range('0', '9')) - ) >> -(set("eE") >> -expr('-') >> +range('0', '9')) - ); -rule Num = Space >> _Num; -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)) -#define opWord(str) (Space >> str >> not_(AlphaNum)) -#define op(str) (Space >> str) - -rule Name = user(SpaceName, [](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); - std::string name; - st->buffer >> name; - st->buffer.str(""); - st->buffer.clear(); - auto it = st->keywords.find(name); - return it == st->keywords.end(); -}); - -rule self = expr('@'); -rule self_name = '@' >> _Name; -rule self_class = expr("@@"); -rule self_class_name = "@@" >> _Name; - -rule SelfName = Space >> (self_class_name | self_class | self_name | self); -rule KeyName = SelfName | Space >> _Name; -rule VarArg = Space >> "..."; - -rule check_indent = user(Indent, [](const item_t& item) +std::string& trim(std::string& s) { - int indent = 0; - for (input_it i = item.begin; i != item.end; ++i) - { - switch (*i) - { - case ' ': indent++; break; - case '\t': indent += 4; break; - } - } - State* st = reinterpret_cast(item.user_data); - return st->indents.top() == indent; -}); -rule CheckIndent = and_(check_indent); - -rule advance = user(Indent, [](const item_t& item) -{ - int indent = 0; - for (input_it i = item.begin; i != item.end; ++i) + s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char ch) { - 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) + return !std::isspace(ch); + })); + s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) { - st->indents.push(indent); - return true; - } - return false; -}); -rule Advance = and_(advance); + return !std::isspace(ch); + }).base(), s.end()); + return s; +} -rule push_indent = user(Indent, [](const item_t& item) +const std::string& AstLeaf::getValue() { - int indent = 0; - for (input_it i = item.begin; i != item.end; ++i) + if (_value.empty()) { - switch (*i) + for (auto it = m_begin.m_it; it != m_end.m_it; ++it) { - case ' ': indent++; break; - case '\t': indent += 4; break; + char ch = static_cast(*it); + _value.append(&ch, 1); } + return trim(_value); } - State* st = reinterpret_cast(item.user_data); - st->indents.push(indent); - return true; -}); -rule PushIndent = and_(push_indent); + return _value; +} -rule PreventIndent = user(true_(), [](const item_t& item) +#define AST_IMPL(type) \ + ast __##type##_t(type); + +AST_IMPL(Num) +AST_IMPL(_Name) +AST_IMPL(Name) +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(ImportName) +AST_IMPL(Import) +AST_IMPL(ExpListLow) +AST_IMPL(ExpList) +AST_IMPL(Return) +AST_IMPL(With) +AST_IMPL(SwitchCase) +AST_IMPL(Switch) +AST_IMPL(IfCond) +AST_IMPL(IfElseIf) +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(CompClause) +AST_IMPL(CompInner) +AST_IMPL(Assign) +AST_IMPL(update_op) +AST_IMPL(Update) +AST_IMPL(BinaryOperator) +AST_IMPL(Assignable) +AST_IMPL(exp_op_value) +AST_IMPL(Exp) +AST_IMPL(Callable) +AST_IMPL(ChainValue) +AST_IMPL(simple_table) +AST_IMPL(SimpleValue) +AST_IMPL(Chain) +AST_IMPL(Value) +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(FnArgs) +AST_IMPL(chain_call) +AST_IMPL(chain_item) +AST_IMPL(DotChainItem) +AST_IMPL(ColonChainItem) +AST_IMPL(chain_dot_chain) +AST_IMPL(ChainItem) +AST_IMPL(ChainItems) +AST_IMPL(invoke_chain) +AST_IMPL(ColonChain) +AST_IMPL(default_value) +AST_IMPL(Slice) +AST_IMPL(Invoke) +AST_IMPL(TableValue) +AST_IMPL(TableLit) +AST_IMPL(TableBlock) +AST_IMPL(class_member_list) +AST_IMPL(ClassLine) +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(KeyValue) +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(ArgBlock) +AST_IMPL(invoke_args_with_table) +AST_IMPL(InvokeArgs) +AST_IMPL(const_value) +AST_IMPL(unary_exp) +AST_IMPL(Assignment) +AST_IMPL(if_else_line) +AST_IMPL(unless_line) +AST_IMPL(statement_appendix) +AST_IMPL(BreakLoop) +AST_IMPL(Statement) +AST_IMPL(Body) +AST_IMPL(Line) +AST_IMPL(Block) +AST_IMPL(BlockEnd) + +void Num_t::visit(void* ud) { - State* st = reinterpret_cast(item.user_data); - st->indents.push(-1); - return true; -}); + Data* data = static_cast(ud); + std::string str = data->conv.to_bytes(&*m_begin.m_it, &*m_end.m_it); + data->buffer << trim(str); +} -rule PopIndent = user(true_(), [](const item_t& item) +void _Name_t::visit(void* ud) { - 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 = op('*') | op('^'); -rule Local = key("local") >> (local_flag | NameList); - -rule colon_import_name = sym('\\') >> Name; -rule ImportName = colon_import_name | Name; -rule ImportNameList = Seperator >> *SpaceBreak >> ImportName >> *((+SpaceBreak | sym(',') >> *SpaceBreak) >> ImportName); - -extern rule Exp; - -rule Import = key("import") >> ImportNameList >> *SpaceBreak >> key("from") >> Exp; -rule BreakLoop = key("break") | key("continue"); - -extern rule ExpListLow, ExpList, Assign; - -rule Return = key("return") >> -ExpListLow; -rule WithExp = ExpList >> -Assign; - -extern rule DisableDo, PopDo, Body; - -rule With = key("with") >> DisableDo >> ensure(WithExp, PopDo) >> -key("do") >> Body; -rule SwitchCase = key("when") >> ExpList >> -key("then") >> Body; -rule SwitchElse = key("else") >> Body; - -rule SwitchBlock = *EmptyLine >> - Advance >> Seperator >> - SwitchCase >> - *(+Break >> SwitchCase) >> - -(+Break >> SwitchElse) >> - PopIndent; - -rule Switch = key("switch") >> - DisableDo >> ensure(Exp, PopDo) >> - -key("do") >> -Space >> Break >> SwitchBlock; - -rule IfCond = Exp >> -Assign; -rule IfElseIf = -(Break >> *EmptyLine >> CheckIndent) >> key("elseif") >> IfCond >> -key("then") >> Body; -rule IfElse = -(Break >> *EmptyLine >> CheckIndent) >> key("else") >> Body; -rule If = key("if") >> IfCond >> -key("then") >> Body >> Seperator >> *IfElseIf >> -IfElse; -rule Unless = key("unless") >> IfCond >> -key("then") >> Body >> Seperator >> *IfElseIf >> -IfElse; - -rule While = key("while") >> DisableDo >> ensure(Exp, PopDo) >> -key("do") >> Body; - -rule for_step_value = sym(',') >> Exp; -rule for_args = Name >> sym('=') >> Exp >> sym(',') >> Exp >> -for_step_value; - -rule For = key("for") >> DisableDo >> - ensure(for_args, PopDo) >> - -key("do") >> Body; - -extern rule AssignableNameList; - -rule for_in = sym('*') >> Exp | ExpList; - -rule ForEach = key("for") >> AssignableNameList >> key("in") >> - DisableDo >> ensure(for_in, PopDo) >> - -key("do") >> Body; + Data* data = static_cast(ud); + data->buffer << getValue(); +} -rule Do = user(key("do") >> Body, [](const item_t& item) +void Name_t::visit(void* ud) { - State* st = reinterpret_cast(item.user_data); - return st->doStack.empty() || st->doStack.top(); -}); + name->visit(ud); +} -rule DisableDo = user(true_(), [](const item_t& item) +void self_t::visit(void* ud) { - State* st = reinterpret_cast(item.user_data); - st->doStack.push(false); - return true; -}); + Data* data = static_cast(ud); + data->buffer << "self"; +} -rule PopDo = user(true_(), [](const item_t& item) +void self_name_t::visit(void* ud) { - State* st = reinterpret_cast(item.user_data); - st->doStack.pop(); - return true; -}); - -extern rule CompInner; - -rule Comprehension = sym('[') >> Exp >> CompInner >> sym(']'); -rule comp_value = sym(',') >> Exp; -rule TblComprehension = sym('{') >> (Exp >> -comp_value) >> CompInner >> sym('}'); - -extern rule CompForEach, CompFor, CompClause; - -rule CompInner = (CompForEach | CompFor) >> Seperator >> *CompClause; -rule star_exp = sym('*') >> Exp; -rule CompForEach = key("for") >> AssignableNameList >> key("in") >> (star_exp | Exp); -rule CompFor = key("for") >> Name >> sym('=') >> Exp >> sym(',') >> Exp >> -for_step_value; -rule CompClause = CompFor | CompForEach | key("when") >> Exp; - -extern rule TableBlock; - -rule Assign = sym('=') >> (With | If | Switch | TableBlock | ExpListLow); - -rule update_op = - sym("..=") | - sym("+=") | - sym("-=") | - sym("*=") | - sym("/=") | - sym("%=") | - sym("or=") | - sym("and=") | - sym("&=") | - sym("|=") | - sym(">>=") | - sym("<<="); - -rule Update = update_op >> Exp; - -rule CharOperators = Space >> set("+-*/%^><|&"); -rule WordOperators = - opWord("or") | - opWord("and") | - op("<=") | - op(">=") | - op("~=") | - op("!=") | - op("==") | - op("..") | - op("<<") | - op(">>") | - op("//"); - -rule BinaryOperator = (WordOperators | CharOperators) >> *SpaceBreak; - -extern rule Chain; - -rule Assignable = Chain | Name | SelfName; - -extern rule Value; - -rule exp_op_value = BinaryOperator >> Value; -rule Exp = Value >> *exp_op_value; - -extern rule Callable, InvokeArgs; - -rule ChainValue = (Chain | Callable) >> -InvokeArgs; - -extern rule KeyValue, String, SimpleValue; - -rule simple_table = Seperator >> KeyValue >> *(sym(',') >> KeyValue); -rule Value = SimpleValue | simple_table | ChainValue | String; - -extern rule LuaString; - -rule single_string_inner = expr("\\'") | "\\\\" | not_(expr('\'')) >> Any; -rule SingleString = symx('\'') >> *single_string_inner >> sym('\''); -rule interp = symx("#{") >> Exp >> sym('}'); -rule double_string_plain = expr("\\\"") | "\\\\" | not_(expr('"')) >> Any; -rule double_string_inner = +(not_(interp) >> double_string_plain); -rule double_string_content = double_string_inner | interp; -rule DoubleString = symx('"') >> Seperator >> *double_string_content >> sym('"'); -rule String = Space >> (DoubleString | SingleString | LuaString); - -rule lua_string_open = '[' >> *expr('=') >> '['; -rule lua_string_close = ']' >> *expr('=') >> ']'; + Data* data = static_cast(ud); + data->buffer << (data->callerStack.top() ? "self:" : "self."); + name->visit(ud); +} -rule LuaStringOpen = user(lua_string_open, [](const item_t& item) +void self_class_t::visit(void* ud) { - size_t count = std::distance(item.begin, item.end); - State* st = reinterpret_cast(item.user_data); - st->stringOpen = count; - return true; -}); + Data* data = static_cast(ud); + data->buffer << "self.__class"; +} -rule LuaStringClose = user(lua_string_close, [](const item_t& item) +void self_class_name_t::visit(void* ud) { - size_t count = std::distance(item.begin, item.end); - State* st = reinterpret_cast(item.user_data); - return st->stringOpen == count; -}); - -rule LuaStringContent = *(not_(LuaStringClose) >> (Break | Any)); + Data* data = static_cast(ud); + data->buffer << (data->callerStack.top() ? "self.__class:" : "self.__class."); + name->visit(ud); +} -rule LuaString = user(LuaStringOpen >> -Break >> LuaStringContent >> LuaStringClose, [](const item_t& item) +void SelfName_t::visit(void* ud) { - State* st = reinterpret_cast(item.user_data); - st->stringOpen = -1; - return true; -}); - -rule Parens = sym('(') >> *SpaceBreak >> Exp >> *SpaceBreak >> sym(')'); -rule Callable = Name | SelfName | VarArg | Parens; -rule FnArgsExpList = Exp >> *((Break | sym(',')) >> White >> Exp); - -rule FnArgs = Seperator >> -( - ( - symx('(') >> *SpaceBreak >> -FnArgsExpList >> *SpaceBreak >> sym(')') - ) | ( - sym('!') >> not_(expr('=')) - ) -); - -extern rule ChainItems, DotChainItem, ColonChain; - -rule chain_call = (Callable | String) >> ChainItems; -rule chain_item = not_(set(".\\")) >> ChainItems; -rule chain_dot_chain = DotChainItem >> -ChainItems; - -rule Chain = - chain_call | - chain_item | - Space >> (chain_dot_chain | ColonChain); - -extern rule ChainItem; - -rule chain_with_colon = +ChainItem >> -ColonChain; -rule ChainItems = Seperator >> (chain_with_colon | ColonChain); - -extern rule Invoke, Slice; - -rule Index = symx('[') >> Exp >> sym(']'); -rule ChainItem = Invoke | DotChainItem | Slice | Index; -rule DotChainItem = symx('.') >> _Name; -rule ColonChainItem = symx('\\') >> _Name; -rule invoke_chain = Invoke >> -ChainItems; -rule ColonChain = ColonChainItem >> -invoke_chain; - -rule default_value = true_(); -rule Slice = - symx('[') >> - (Exp | default_value) >> - sym(',') >> - (Exp | default_value) >> - (sym(',') >> Exp | default_value) >> - sym(']'); - -rule Invoke = - FnArgs | - SingleString | - DoubleString | - and_(expr('[')) >> LuaString; - -extern rule TableValueList, TableLitLine; - -rule TableValue = KeyValue | Exp; - -rule table_lit_lines = SpaceBreak >> TableLitLine >> *(-sym(',') >> SpaceBreak >> TableLitLine) >> -sym(','); - -rule TableLit = - sym('{') >> Seperator >> - -TableValueList >> - -sym(',') >> - -table_lit_lines >> - White >> sym('}'); - -rule TableValueList = TableValue >> *(sym(',') >> TableValue); - -rule TableLitLine = -( - PushIndent >> (TableValueList >> PopIndent | PopIndent) -) | ( - Space -); - -extern rule KeyValueLine; - -rule TableBlockInner = Seperator >> KeyValueLine >> *(+(SpaceBreak) >> KeyValueLine); -rule TableBlock = +(SpaceBreak) >> Advance >> ensure(TableBlockInner, PopIndent); - -extern rule Statement; - -rule class_member_list = Seperator >> KeyValue >> *(sym(',') >> KeyValue); -rule ClassLine = CheckIndent >> (class_member_list | Statement | Exp) >> -sym(','); -rule ClassBlock = +(SpaceBreak) >> Advance >>Seperator >> ClassLine >> *(+(SpaceBreak) >> ClassLine) >> PopIndent; - -rule ClassDecl = - key("class") >> not_(expr(':')) >> - -Assignable >> - -(key("extends") >> PreventIndent >> ensure(Exp, PopIndent)) >> - -ClassBlock; - -rule export_values = NameList >> -(sym('=') >> ExpListLow); -rule export_op = op('*') | op('^'); -rule Export = key("export") >> (ClassDecl | export_op | export_values); - -rule variable_pair = sym(':') >> not_(SomeSpace) >> Name; - -rule normal_pair = -( - KeyName | - sym('[') >> Exp >> sym(']') | - Space >> DoubleString | - Space >> SingleString -) >> -symx(':') >> -(Exp | TableBlock | +(SpaceBreak) >> Exp); - -rule KeyValue = variable_pair | normal_pair; - -rule KeyValueList = KeyValue >> *(sym(',') >> KeyValue); -rule KeyValueLine = CheckIndent >> KeyValueList >> -sym(','); - -rule FnArgDef = (Name | SelfName) >> -(sym('=') >> Exp); - -rule FnArgDefList = Seperator >> -( - ( - FnArgDef >> - *((sym(',') | Break) >> White >> FnArgDef) >> - -((sym(',') | Break) >> White >> VarArg) - ) | ( - VarArg - ) -); - -rule outer_var_shadow = key("using") >> (NameList | Space >> expr("nil")); - -rule FnArgsDef = sym('(') >> White >> -FnArgDefList >> -outer_var_shadow >> White >> sym(')'); -rule fn_arrow = sym("->") | sym("=>"); -rule FunLit = -FnArgsDef >> fn_arrow >> -Body; - -rule NameList = Seperator >> Name >> *(sym(',') >> Name); -rule NameOrDestructure = Name | TableLit; -rule AssignableNameList = Seperator >> NameOrDestructure >> *(sym(',') >> NameOrDestructure); - -rule ExpList = Seperator >> Exp >> *(sym(',') >> Exp); -rule ExpListLow = Seperator >> Exp >> *((sym(',') | sym(';')) >> Exp); - -rule ArgLine = CheckIndent >> Exp >> *(sym(',') >> Exp); -rule ArgBlock = Seperator >> ArgLine >> *(sym(',') >> SpaceBreak >> ArgLine) >> PopIndent; - -rule invoke_args_with_table = - sym(',') >> - ( - TableBlock | - SpaceBreak >> Advance >> ArgBlock >> -TableBlock - ); - -rule InvokeArgs = - not_(expr('-')) >> - ( - ExpList >> -(invoke_args_with_table | TableBlock) | - TableBlock - ); - -rule const_value = key("nil") | key("true") | key("false"); -rule minus_exp = sym('-') >> not_(SomeSpace) >> Exp; -rule sharp_exp = sym('#') >> Exp; -rule tilde_exp = sym('~') >> Exp; -rule not_exp = key("not") >> Exp; -rule unary_exp = minus_exp | sharp_exp | tilde_exp | not_exp; - -rule SimpleValue = - const_value | - If | Unless | Switch | With | ClassDecl | ForEach | For | While | Do | - unary_exp | - TblComprehension | TableLit | Comprehension | FunLit | Num; - -rule Assignment = ExpList >> (Update | Assign); - -rule if_else_line = key("if") >> Exp >> (key("else") >> Exp | default_value); -rule unless_line = key("unless") >> Exp; - -rule statement_appendix = (if_else_line | unless_line | CompInner) >> Space; -rule Statement = -( - Import | While | With | For | ForEach | - Switch | Return | Local | Export | BreakLoop | - Assignment | ExpList -) >> 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 BlockEnd = Block >> eof(); + name->visit(ud); +} -class AstLeaf : public ast_node +void KeyName_t::visit(void* ud) { -public: - const std::string& getValue() - { - if (_value.empty()) - { - for (auto it = m_begin.m_it; it != m_end.m_it; ++it) - { - char ch = static_cast(*it); - _value.append(&ch, 1); - } - return trim(_value); - } - return _value; - } -private: - std::string _value; -}; - -#define AST_LEAF(type) \ -class type##_t : public AstLeaf \ -{ \ -public: \ - virtual int get_type() override { return ast_type(); } - -#define AST_NODE(type) \ -class type##_t : public ast_container \ -{ \ -public: \ - virtual int get_type() override { return ast_type(); } - -#define AST_END(type) \ -}; \ -ast __##type##_t(type); - -AST_LEAF(Num) - virtual void visit(void* ud) override - { - Data* data = static_cast(ud); - std::string str = data->conv.to_bytes(&*m_begin.m_it, &*m_end.m_it); - data->buffer << trim(str); - } -AST_END(Num) - -AST_LEAF(_Name) - virtual void visit(void* ud) override - { - Data* data = static_cast(ud); - data->buffer << getValue(); - } -AST_END(_Name) - -AST_NODE(Name) - ast_ptr<_Name_t> name; - virtual void visit(void* ud) override - { - name->visit(ud); - } -AST_END(Name) - -AST_LEAF(self) - virtual void visit(void* ud) override - { - Data* data = static_cast(ud); - data->buffer << "self"; - } -AST_END(self) - -AST_NODE(self_name) - ast_ptr<_Name_t> name; - virtual void visit(void* ud) override - { - Data* data = static_cast(ud); - data->buffer << (data->callerStack.top() ? "self:" : "self."); - name->visit(ud); - } -AST_END(self_name) - -AST_LEAF(self_class) - virtual void visit(void* ud) override - { - Data* data = static_cast(ud); - data->buffer << "self.__class"; - } -AST_END(self_class) - -AST_NODE(self_class_name) - ast_ptr<_Name_t> name; - virtual void visit(void* ud) override - { - Data* data = static_cast(ud); - data->buffer << (data->callerStack.top() ? "self.__class:" : "self.__class."); - name->visit(ud); - } -AST_END(self_class_name) + name->visit(ud); +} -AST_NODE(SelfName) - ast_ptr name; // self_class_name_t | self_class_t | self_name_t | self_t - virtual void visit(void* ud) override - { - name->visit(ud); - } -AST_END(SelfName) +void VarArg_t::visit(void* ud) +{ + Data* data = static_cast(ud); + data->buffer << "..."; +} -AST_NODE(KeyName) - ast_ptr name; // SelfName_t | _Name_t - virtual void visit(void* ud) override - { +void NameList_t::visit(void* ud) +{ + Data* data = static_cast(ud); + auto it = names.objects().begin(); + Name_t* name = *it; + name->visit(ud); + ++it; + for (; it != names.objects().end(); ++it) + { + name = *it; + data->buffer << ", "; name->visit(ud); } -AST_END(KeyName) +} -AST_LEAF(VarArg) - virtual void visit(void* ud) override +void Import_t::visit(void* ud) +{ + Data* data = static_cast(ud); + std::vector> nameItems; + nameItems.reserve(names.objects().size()); + for (ImportName_t* importName : names.objects()) { - Data* data = static_cast(ud); - data->buffer << "..."; + if (Name_t* name = ast_cast(importName->name)) + { + nameItems.push_back(std::make_tuple(&name->name->getValue(), false)); + } + else + { + colon_import_name_t* colonName = ast_cast(importName->name); + nameItems.push_back(std::make_tuple(&colonName->name->name->getValue(), true)); + } } -AST_END(VarArg) - -AST_LEAF(local_flag) -AST_END(local_flag) - -AST_LEAF(Seperator) -AST_END(Seperator) - -AST_NODE(NameList) - ast_ptr sep; - ast_list names; - virtual void visit(void* ud) override + data->buffer << "local "; + for (const auto& item : nameItems) { - Data* data = static_cast(ud); - auto it = names.objects().begin(); - Name_t* name = *it; - name->visit(ud); - ++it; - for (; it != names.objects().end(); ++it) + data->buffer << *std::get<0>(item); + if (&item != &nameItems.back()) { - name = *it; data->buffer << ", "; - name->visit(ud); } } -AST_END(NameList) + data->endLine(); -AST_NODE(Local) - ast_ptr name; // local_flag_t | NameList_t -AST_END(Local) + data->beginLine(); + data->pushScope(); + data->buffer << "do"; + data->endLine(); -AST_NODE(colon_import_name) - ast_ptr name; -AST_END(colon_import_name) + std::string fromObj = data->getNewLocalObj(); -AST_NODE(Exp) - ast_ptr value; - ast_list opValues; -AST_END(Exp) + data->beginLine(); + data->buffer << "local " << fromObj << " = "; + exp->visit(ud); + data->endLine(); -AST_NODE(ImportName) - ast_ptr name; // colon_import_name_t | Name_t -AST_END(ImportName) - -AST_NODE(Import) - ast_ptr sep; - ast_list names; - ast_ptr exp; - virtual void visit(void* ud) override + data->beginLine(); + for (const auto& item : nameItems) { - Data* data = static_cast(ud); - std::vector> nameItems; - nameItems.reserve(names.objects().size()); - for (ImportName_t* importName : names.objects()) - { - if (Name_t* name = ast_cast(importName->name)) - { - nameItems.push_back(std::make_tuple(&name->name->getValue(), false)); - } - else - { - colon_import_name_t* colonName = ast_cast(importName->name); - nameItems.push_back(std::make_tuple(&colonName->name->name->getValue(), true)); - } - } - data->buffer << "local "; - for (const auto& item : nameItems) - { - data->buffer << *std::get<0>(item); - if (&item != &nameItems.back()) - { - data->buffer << ", "; - } - } - data->endLine(); - - data->beginLine(); - data->pushScope(); - data->buffer << "do"; - data->endLine(); - - std::string fromObj = data->getNewLocalObj(); - - data->beginLine(); - data->buffer << "local " << fromObj << " = "; - ((ast_node*)exp.get())->visit(ud); - data->endLine(); - - data->beginLine(); - for (const auto& item : nameItems) + data->buffer << *std::get<0>(item); + if (&item != &nameItems.back()) { - data->buffer << *std::get<0>(item); - if (&item != &nameItems.back()) - { - data->buffer << ", "; - } + data->buffer << ", "; } - data->buffer << " = "; - for (const auto& item : nameItems) + } + data->buffer << " = "; + for (const auto& item : nameItems) + { + if (std::get<1>(item)) { - if (std::get<1>(item)) - { - data->pushScope(); - data->buffer << "(function()"; - data->endLine(); + data->pushScope(); + data->buffer << "(function()"; + data->endLine(); - std::string varBase = data->getNewLocalBase(); + std::string varBase = data->getNewLocalBase(); - data->beginLine(); - data->buffer << "local " << varBase << " = " << fromObj; - data->endLine(); + data->beginLine(); + data->buffer << "local " << varBase << " = " << fromObj; + data->endLine(); - std::string varFn = data->getNewLocalFn(); + std::string varFn = data->getNewLocalFn(); - data->beginLine(); - data->buffer << "local " << varFn << " = " << varBase << '.' << *std::get<0>(item); - data->endLine(); + data->beginLine(); + data->buffer << "local " << varFn << " = " << varBase << '.' << *std::get<0>(item); + data->endLine(); - data->beginLine(); - data->buffer << "return function(...)"; - data->endLine(); + data->beginLine(); + data->buffer << "return function(...)"; + data->endLine(); - data->beginLine(); - data->pushScope(); - data->buffer << varFn << '(' << varBase << ", ...)"; - data->endLine(); + data->beginLine(); + data->pushScope(); + data->buffer << varFn << '(' << varBase << ", ...)"; + data->endLine(); - data->beginLine(); - data->buffer << "end"; - data->popScope(); - data->endLine(); + data->beginLine(); + data->buffer << "end"; + data->popScope(); + data->endLine(); - data->beginLine(); - data->buffer << "end)()"; - data->popScope(); - } - else - { - data->buffer << fromObj << '.' << *std::get<0>(item); - } - if (&item != &nameItems.back()) - { - data->buffer << ", "; - } + data->beginLine(); + data->buffer << "end)()"; + data->popScope(); } - data->endLine(); - - data->beginLine(); - data->buffer << "end"; - data->popScope(); - } -AST_END(Import) - -AST_NODE(ExpListLow) - ast_ptr sep; - ast_list exprs; - virtual void visit(void* ud) override - { - Data* data = static_cast(ud); - for (Exp_t* expr : exprs.objects()) + else { - ((ast_node*)expr)->visit(ud); - if (expr != exprs.objects().back()) - { - data->buffer << ", "; - } + data->buffer << fromObj << '.' << *std::get<0>(item); } - } -AST_END(ExpListLow) - -AST_NODE(ExpList) - ast_ptr sep; - ast_list exprs; - virtual void visit(void* ud) override - { - Data* data = static_cast(ud); - for (Exp_t* expr : exprs.objects()) + if (&item != &nameItems.back()) { - ((ast_node*)expr)->visit(ud); - if (expr != exprs.objects().back()) - { - data->buffer << ", "; - } + data->buffer << ", "; } } -AST_END(ExpList) + data->endLine(); + + data->beginLine(); + data->buffer << "end"; + data->popScope(); +} -AST_NODE(Return) - ast_ptr valueList; - virtual void visit(void* ud) override +void ExpListLow_t::visit(void* ud) +{ + Data* data = static_cast(ud); + for (Exp_t* expr : exprs.objects()) { - Data* data = static_cast(ud); - data->buffer << "return"; - if (valueList && !valueList->exprs.objects().empty()) + expr->visit(ud); + if (expr != exprs.objects().back()) { - data->buffer << ' '; - valueList->visit(ud); + data->buffer << ", "; } } -AST_END(Return) - -class Assign_t; -class Body_t; +} -AST_NODE(With) - ast_ptr valueList; - ast_ptr assigns; - ast_ptr body; - /* - (function() - do - local _with_0 = Something() - _with_0:write("hello world") - return _with_0 - end - end)() - */ - virtual void visit(void* ud) override +void ExpList_t::visit(void* ud) +{ + Data* data = static_cast(ud); + for (Exp_t* expr : exprs.objects()) { - Data* data = static_cast(ud); - for (Exp_t* expr : valueList->exprs.objects()) + expr->visit(ud); + if (expr != exprs.objects().back()) { + data->buffer << ", "; } - ((ast_node*)expr)->visit(ud); - if (expr != exprs.objects().back()) - { - data->buffer << ", "; - } } -AST_END(With) - -AST_NODE(SwitchCase) - ast_ptr valueList; - ast_ptr body; -AST_END(SwitchCase) - -AST_NODE(Switch) - ast_ptr target; - ast_ptr sep; - ast_list branches; - ast_ptr lastBranch; -AST_END(Switch) - -AST_NODE(IfCond) - ast_ptr condition; - ast_ptr assign; -AST_END(IfCond) - -AST_NODE(IfElseIf) - ast_ptr condition; - ast_ptr body; -AST_END(IfElseIf) - -AST_NODE(If) - ast_ptr firstCondition; - ast_ptr firstBody; - ast_ptr sep; - ast_list branches; - ast_ptr lastBranch; -AST_END(If) - -AST_NODE(Unless) - ast_ptr firstCondition; - ast_ptr firstBody; - ast_ptr sep; - ast_list branches; - ast_ptr lastBranch; -AST_END(Unless) - -AST_NODE(While) - ast_ptr condition; - ast_ptr body; -AST_END(While) - -AST_NODE(for_step_value) - ast_ptr value; -AST_END(for_step_value) - -AST_NODE(For) - ast_ptr varName; - ast_ptr startValue; - ast_ptr stopValue; - ast_ptr stepValue; - ast_ptr body; -AST_END(For) - -class AssignableNameList_t; - -AST_NODE(ForEach) - ast_ptr nameList; - ast_ptr loopValue; // Exp_t | ExpList_t - ast_ptr body; -AST_END(ForEach) - -AST_NODE(Do) - ast_ptr body; -AST_END(Do) - -class CompInner_t; - -AST_NODE(Comprehension) - ast_ptr value; - ast_ptr forLoop; -AST_END(Comprehension) - -AST_NODE(comp_value) - ast_ptr value; -AST_END(comp_value) - -AST_NODE(TblComprehension) - ast_ptr key; - ast_ptr value; - ast_ptr forLoop; -AST_END(TblComprehension) - -AST_NODE(star_exp) - ast_ptr value; -AST_END(star_exp) - -AST_NODE(CompForEach) - ast_ptr nameList; - ast_ptr loopValue; // star_exp_t | Exp_t -AST_END(CompForEach) - -AST_NODE(CompFor) - ast_ptr varName; - ast_ptr startValue; - ast_ptr stopValue; - ast_ptr stepValue; -AST_END(CompFor) - -AST_NODE(CompClause) - ast_ptr nestExp; // CompFor_t | CompForEach_t | Exp_t -AST_END(CompClause) - -AST_NODE(CompInner) - ast_ptr compFor; // CompFor_t | CompForEach_t - ast_ptr sep; - ast_list clauses; -AST_END(CompInner) - -class TableBlock_t; - -AST_NODE(Assign) - ast_ptr value; // With_t | If_t | Switch_t | TableBlock_t | ExpListLow_t -AST_END(Assign) - -AST_LEAF(update_op) -AST_END(update_op) - -AST_NODE(Update) - ast_ptr op; - ast_ptr value; -AST_END(Update) - -AST_LEAF(BinaryOperator) -AST_END(BinaryOperator) - -class Chain_t; - -AST_NODE(Assignable) - ast_ptr item; // Chain_t | Name_t | SelfName_t -AST_END(Assignable) - -class Value_t; - -AST_NODE(exp_op_value) - ast_ptr op; - ast_ptr value; -AST_END(exp_op_value) - -AST_NODE(Callable) - ast_ptr item; // Name_t | SelfName_t | VarArg_t | Parens_t -AST_END(Callable) - -class InvokeArgs_t; - -AST_NODE(ChainValue) - ast_ptr caller; // Chain_t | Callable_t - ast_ptr arguments; +} - virtual void visit(void* ud) override +void Return_t::visit(void* ud) +{ + Data* data = static_cast(ud); + data->buffer << "return"; + if (valueList && !valueList->exprs.objects().empty()) { - + data->buffer << ' '; + valueList->visit(ud); } -AST_END(ChainValue) - -class KeyValue_t; - -AST_NODE(simple_table) - ast_ptr sep; - ast_list pairs; -AST_END(simple_table) - -class String_t; - -AST_NODE(SimpleValue) - ast_ptr value; /* - const_value_t | - If_t | Unless_t | Switch_t | With_t | ClassDecl_t | ForEach_t | For_t | While_t | Do_t | - unary_exp_t | - TblComprehension_t | TableLit_t | Comprehension_t | FunLit_t | Num_t; - */ -AST_END(SimpleValue) - -AST_NODE(Chain) - ast_ptr item; // chain_call_t | chain_item_t | chain_dot_chain_t | ColonChain_t -AST_END(Chain) +} -AST_NODE(Value) - ast_ptr item; // SimpleValue_t | simple_table_t | ChainValue_t | String_t - ast_node* getFlattenedNode() +void With_t::visit(void* ud) +{ + Data* data = static_cast(ud); + data->buffer << "return"; + for (Exp_t* expr : valueList->exprs.objects()) { - if (SimpleValue_t* simpleValue = ast_cast(item)) + if (assigns && (!expr->opValues.objects().empty() || expr->value->getFlattened())) { - return simpleValue->value; + throw std::logic_error("left hand expression is not assignable."); } - else if (simple_table_t* simple_table = ast_cast(item)) - { - return simple_table; - } - else if (ChainValue_t* chainValue = ast_cast(item)) - { - if (chainValue->arguments) - { - return chainValue; - } - else - { - if (Chain_t* chain = ast_cast(chainValue->caller)) - { - return chain->item; - } - else if (Callable_t* callable = ast_cast(chainValue->caller)) - { - return callable->item; - } - } - } - return item; - } -AST_END(Value) - -AST_LEAF(LuaString) -AST_END(LuaString) - -AST_LEAF(SingleString) -AST_END(SingleString) - -AST_LEAF(double_string_inner) -AST_END(double_string_inner) - -AST_NODE(double_string_content) - ast_ptr content; // double_string_inner_t | Exp_t -AST_END(double_string_content) - -AST_NODE(DoubleString) - ast_ptr sep; - ast_list segments; -AST_END(DoubleString) - -AST_NODE(String) - ast_ptr str; // DoubleString_t | SingleString_t | LuaString_t -AST_END(String) - -AST_NODE(Parens) - ast_ptr expr; -AST_END(Parens) - -AST_NODE(FnArgs) - ast_ptr sep; - ast_list args; -AST_END(FnArgs) - -class ChainItems_t; - -AST_NODE(chain_call) - ast_ptr caller; // Callable_t | String_t - ast_ptr chain; -AST_END(chain_call) - -AST_NODE(chain_item) - ast_ptr chain; -AST_END(chain_item) - -AST_NODE(DotChainItem) - ast_ptr<_Name_t> name; -AST_END(DotChainItem) - -AST_NODE(ColonChainItem) - ast_ptr<_Name_t> name; -AST_END(ColonChainItem) - -AST_NODE(chain_dot_chain) - ast_ptr caller; - ast_ptr chain; -AST_END(chain_dot_chain) - -class ColonChain_t; - -class Invoke_t; -class Slice_t; - -AST_NODE(ChainItem) - ast_ptr item; // Invoke_t | DotChainItem_t | Slice_t | [Exp_t] -AST_END(ChainItem) - -AST_NODE(ChainItems) - ast_ptr sep; - ast_list simpleChain; - ast_ptr colonChain; -AST_END(ChainItems) - -AST_NODE(invoke_chain) - ast_ptr invoke; - ast_ptr chain; -AST_END(invoke_chain) - -AST_NODE(ColonChain) - ast_ptr colonChain; - ast_ptr invokeChain; -AST_END(ColonChain) - -AST_LEAF(default_value) -AST_END(default_value) - -AST_NODE(Slice) - ast_ptr startValue; // Exp_t | default_value_t - ast_ptr stopValue; // Exp_t | default_value_t - ast_ptr stepValue; // Exp_t | default_value_t -AST_END(Slice) - -AST_NODE(Invoke) - ast_ptr argument; // FnArgs_t | SingleString_t | DoubleString_t | LuaString_t -AST_END(Invoke) - -class KeyValue_t; - -AST_NODE(TableValue) - ast_ptr value; // KeyValue_t | Exp_t -AST_END(TableValue) - -AST_NODE(TableLit) - ast_ptr sep; - ast_list values; -AST_END(TableLit) - -AST_NODE(TableBlock) - ast_ptr sep; - ast_list values; -AST_END(TableBlock) - -AST_NODE(class_member_list) - ast_ptr sep; - ast_list values; -AST_END(class_member_list) - -AST_NODE(ClassLine) - ast_ptr content; // class_member_list_t | Statement_t | Exp_t -AST_END(ClassLine) - -AST_NODE(ClassBlock) - ast_ptr sep; - ast_list lines; -AST_END(ClassBlock) - -AST_NODE(ClassDecl) - ast_ptr name; - ast_ptr extend; - ast_ptr body; -AST_END(ClassDecl) - -AST_NODE(export_values) - ast_ptr nameList; - ast_ptr valueList; -AST_END(export_values) - -AST_LEAF(export_op) -AST_END(export_op) - -AST_NODE(Export) - ast_ptr item; // ClassDecl_t | export_op_t | export_values_t -AST_END(Export) - -AST_NODE(variable_pair) - ast_ptr name; -AST_END(variable_pair) - -AST_NODE(normal_pair) - ast_ptr key; // KeyName_t | [Exp_t] | DoubleString_t | SingleString_t - ast_ptr value; // Exp_t | TableBlock_t -AST_END(normal_pair) - -AST_NODE(KeyValue) - ast_ptr item; // variable_pair_t | normal_pair_t -AST_END(KeyValue) - -AST_NODE(FnArgDef) - ast_ptr name; // Name_t | SelfName_t - ast_ptr defaultValue; -AST_END(FnArgDef) - -AST_NODE(FnArgDefList) - ast_ptr sep; - ast_list definitions; - ast_ptr varArg; -AST_END(FnArgDefList) - -AST_NODE(outer_var_shadow) - ast_ptr varList; -AST_END(outer_var_shadow) - -AST_NODE(FnArgsDef) - ast_ptr defList; - ast_ptr shadowOption; -AST_END(FnArgsDef) - -AST_LEAF(fn_arrow) -AST_END(fn_arrow) - -AST_NODE(FunLit) - ast_ptr argsDef; - ast_ptr arrow; - ast_ptr body; -AST_END(FunLit) - -AST_NODE(NameOrDestructure) - ast_ptr item; // Name_t | TableLit_t -AST_END(NameOrDestructure) - -AST_NODE(AssignableNameList) - ast_ptr sep; - ast_list items; -AST_END(AssignableNameList) - -AST_NODE(ArgBlock) - ast_ptr sep; - ast_list arguments; -AST_END(ArgBlock) - -AST_NODE(invoke_args_with_table) - ast_ptr argBlock; - ast_ptr tableBlock; -AST_END(invoke_args_with_table) - -AST_NODE(InvokeArgs) - ast_ptr argsList; - ast_ptr argsTableBlock; - ast_ptr tableBlock; -AST_END(InvokeArgs) - -AST_LEAF(const_value) -AST_END(const_value) - -AST_NODE(unary_exp) - ast_ptr item; -AST_END(unary_exp) - -AST_NODE(Assignment) - ast_ptr assignable; - ast_ptr target; // Update_t | Assign_t -AST_END(Assignment) - -AST_NODE(if_else_line) - ast_ptr condition; - ast_ptr elseExpr; // Exp_t | default_value_t -AST_END(if_else_line) - -AST_NODE(unless_line) - ast_ptr condition; -AST_END(unless_line) - -AST_NODE(statement_appendix) - ast_ptr item; // if_else_line_t | unless_line_t | CompInner_t -AST_END(statement_appendix) - -AST_LEAF(BreakLoop) -AST_END(BreakLoop) - -AST_NODE(Statement) - ast_ptr content; /* - Import_t | While_t | With_t | For_t | ForEach_t | - Switch_t | Return_t | Local_t | Export_t | BreakLoop_t | - Assignment_t | ExpList_t - */ - ast_ptr appendix; - - virtual void construct(ast_stack& st) override - { - std::wstring_convert>, char32_t> conv; - value = conv.to_bytes(&*m_begin.m_it, &*m_end.m_it); - ast_container::construct(st); + // TODO } - - virtual void visit(void* ud) override + if (valueList && !valueList->exprs.objects().empty()) { - std::cout << value << '\n'; + data->buffer << ' '; + valueList->visit(ud); } - std::string value; -AST_END(Statement) - -class Block_t; +} -AST_NODE(Body) - ast_ptr content; // Block | Statement - virtual void visit(void* ud) override +ast_node* Value_t::getFlattened() +{ + if (SimpleValue_t* simpleValue = ast_cast(item)) { - Data* data = static_cast(ud); - data->pushScope(); - content->visit(ud); - data->popScope(); + return simpleValue->value; } -AST_END(Body) - -AST_NODE(Line) - ast_ptr statment; - int line; - - virtual void construct(ast_stack& st) override + else if (simple_table_t* simple_table = ast_cast(item)) { - ast_container::construct(st); - line = m_begin.m_line; + return simple_table; } - - virtual void visit(void* ud) override + else if (ChainValue_t* chainValue = ast_cast(item)) { - if (statment) + if (chainValue->arguments) { - std::cout << line << ": "; - statment->visit(ud); + return chainValue; } - } -AST_END(Line) - -AST_NODE(Block) - ast_ptr sep; - ast_list lines; - virtual void visit(void* ud) override - { - Data* data = static_cast(ud); - const auto& objs = lines.objects(); - for (auto it = objs.begin(); it != objs.end(); ++it) + else { - Line_t* line = *it; - if (!line->statment) continue; - if (Local_t* local = ast_cast(line->statment->content)) + if (Chain_t* chain = ast_cast(chainValue->caller)) { - if (local_flag_t* local_flag = ast_cast(local->name)) - { - std::vector names; - for (auto cur = it; cur != objs.end(); ++cur) - { - Line_t* item = *cur; - if (!item->statment) continue; - if (Assignment_t* assignment = ast_cast(item->statment->content)) - { - for (Exp_t* expr : assignment->assignable->exprs.objects()) - { - if (ChainValue_t* chainValue = ast_cast(expr->value->item)) - if (Callable_t* callable = ast_cast(chainValue->caller)) - if (Name_t* name = ast_cast(callable->item)) - { - const std::string& value = name->name->getValue(); - if (local_flag->getValue() == "*") - { - names.push_back(&value); - } - else if (std::isupper(value[0])) - { - names.push_back(&value); - } - } - } - } - } - if (!names.empty()) - { - data->beginLine(); - data->buffer << "local "; - auto nameIt = names.begin(); - auto name = *(*nameIt); - data->putLocal(name); - data->buffer << name; - nameIt++; - for (; nameIt != names.end(); ++nameIt) - { - auto name = *(*nameIt); - data->putLocal(name); - data->buffer << ", "; - data->buffer << name; - } - data->endLine(line->m_begin.m_line); - } - } - else - { - NameList_t* nameList = static_cast(local->name.get()); - data->beginLine(); - data->buffer << "local "; - nameList->visit(ud); - for (Name_t* name : nameList->names.objects()) - { - data->putLocal(name->name->getValue()); - } - data->endLine(line->m_begin.m_line); - } + return chain->item; } - else + else if (Callable_t* callable = ast_cast(chainValue->caller)) { - line->visit(ud); + return callable->item; } } } -AST_END(Block) + return item; +} -AST_NODE(BlockEnd) - ast_ptr block; - virtual void visit(void* ud) override - { - Data* data = static_cast(ud); - data->pushScope(); - block->visit(ud); - data->popScope(); - } -AST_END(BlockEnd) +#include int main() { diff --git a/MoonParser/moon_ast.h b/MoonParser/moon_ast.h index 942a2b6..4da4b8d 100644 --- a/MoonParser/moon_ast.h +++ b/MoonParser/moon_ast.h @@ -1,4 +1,591 @@ #pragma once -#include "parserlib.hpp" +#include "moon_parser.h" +template +struct deletable_facet : Facet +{ + template + deletable_facet(Args&& ...args): Facet(std::forward(args)...) {} + ~deletable_facet() {} +}; +typedef std::wstring_convert>, char32_t> Converter; + +std::string& trim(std::string& s); + +class AstLeaf : public ast_node +{ +public: + const std::string& getValue(); +private: + std::string _value; +}; + +#define AST_LEAF(type) \ +extern rule type; \ +class type##_t : public AstLeaf \ +{ \ +public: \ + virtual int get_type() override { return ast_type(); } + +#define AST_NODE(type) \ +extern rule type; \ +class type##_t : public ast_container \ +{ \ +public: \ + virtual int get_type() override { return ast_type(); } + +#define AST_END(type) \ +}; + +AST_LEAF(Num) + virtual void visit(void* ud) override; +AST_END(Num) + +AST_LEAF(_Name) + virtual void visit(void* ud) override; +AST_END(_Name) + +AST_NODE(Name) + ast_ptr<_Name_t> name; + virtual void visit(void* ud) override; +AST_END(Name) + +AST_LEAF(self) + virtual void visit(void* ud) override; +AST_END(self) + +AST_NODE(self_name) + ast_ptr<_Name_t> name; + virtual void visit(void* ud) override; +AST_END(self_name) + +AST_LEAF(self_class) + virtual void visit(void* ud) override; +AST_END(self_class) + +AST_NODE(self_class_name) + ast_ptr<_Name_t> name; + virtual void visit(void* ud) override; +AST_END(self_class_name) + +AST_NODE(SelfName) + ast_ptr name; // self_class_name_t | self_class_t | self_name_t | self_t + virtual void visit(void* ud) override; +AST_END(SelfName) + +AST_NODE(KeyName) + ast_ptr name; // SelfName_t | _Name_t + virtual void visit(void* ud) override; +AST_END(KeyName) + +AST_LEAF(VarArg) + virtual void visit(void* ud) override; +AST_END(VarArg) + +AST_LEAF(local_flag) +AST_END(local_flag) + +AST_LEAF(Seperator) +AST_END(Seperator) + +AST_NODE(NameList) + ast_ptr sep; + ast_list names; + + virtual void visit(void* ud) override; +AST_END(NameList) + +AST_NODE(Local) + ast_ptr name; // local_flag_t | NameList_t +AST_END(Local) + +AST_NODE(colon_import_name) + ast_ptr name; +AST_END(colon_import_name) + +class Exp_t; + +AST_NODE(ImportName) + ast_ptr name; // colon_import_name_t | Name_t +AST_END(ImportName) + +AST_NODE(Import) + ast_ptr sep; + ast_list names; + ast_ptr exp; + virtual void visit(void* ud) override; +AST_END(Import) + +AST_NODE(ExpListLow) + ast_ptr sep; + ast_list exprs; + virtual void visit(void* ud) override; +AST_END(ExpListLow) + +AST_NODE(ExpList) + ast_ptr sep; + ast_list exprs; + virtual void visit(void* ud) override; +AST_END(ExpList) + +AST_NODE(Return) + ast_ptr valueList; + virtual void visit(void* ud) override; +AST_END(Return) + +class Assign_t; +class Body_t; + +AST_NODE(With) + ast_ptr valueList; + ast_ptr assigns; + ast_ptr body; + virtual void visit(void* ud) override; +AST_END(With) + +AST_NODE(SwitchCase) + ast_ptr valueList; + ast_ptr body; +AST_END(SwitchCase) + +AST_NODE(Switch) + ast_ptr target; + ast_ptr sep; + ast_list branches; + ast_ptr lastBranch; +AST_END(Switch) + +AST_NODE(IfCond) + ast_ptr condition; + ast_ptr assign; +AST_END(IfCond) + +AST_NODE(IfElseIf) + ast_ptr condition; + ast_ptr body; +AST_END(IfElseIf) + +AST_NODE(If) + ast_ptr firstCondition; + ast_ptr firstBody; + ast_ptr sep; + ast_list branches; + ast_ptr lastBranch; +AST_END(If) + +AST_NODE(Unless) + ast_ptr firstCondition; + ast_ptr firstBody; + ast_ptr sep; + ast_list branches; + ast_ptr lastBranch; +AST_END(Unless) + +AST_NODE(While) + ast_ptr condition; + ast_ptr body; +AST_END(While) + +AST_NODE(for_step_value) + ast_ptr value; +AST_END(for_step_value) + +AST_NODE(For) + ast_ptr varName; + ast_ptr startValue; + ast_ptr stopValue; + ast_ptr stepValue; + ast_ptr body; +AST_END(For) + +class AssignableNameList_t; + +AST_NODE(ForEach) + ast_ptr nameList; + ast_ptr loopValue; // Exp_t | ExpList_t + ast_ptr body; +AST_END(ForEach) + +AST_NODE(Do) + ast_ptr body; +AST_END(Do) + +class CompInner_t; + +AST_NODE(Comprehension) + ast_ptr value; + ast_ptr forLoop; +AST_END(Comprehension) + +AST_NODE(comp_value) + ast_ptr value; +AST_END(comp_value) + +AST_NODE(TblComprehension) + ast_ptr key; + ast_ptr value; + ast_ptr forLoop; +AST_END(TblComprehension) + +AST_NODE(star_exp) + ast_ptr value; +AST_END(star_exp) + +AST_NODE(CompForEach) + ast_ptr nameList; + ast_ptr loopValue; // star_exp_t | Exp_t +AST_END(CompForEach) + +AST_NODE(CompFor) + ast_ptr varName; + ast_ptr startValue; + ast_ptr stopValue; + ast_ptr stepValue; +AST_END(CompFor) + +AST_NODE(CompClause) + ast_ptr nestExp; // CompFor_t | CompForEach_t | Exp_t +AST_END(CompClause) + +AST_NODE(CompInner) + ast_ptr compFor; // CompFor_t | CompForEach_t + ast_ptr sep; + ast_list clauses; +AST_END(CompInner) + +class TableBlock_t; + +AST_NODE(Assign) + ast_ptr value; // With_t | If_t | Switch_t | TableBlock_t | ExpListLow_t +AST_END(Assign) + +AST_LEAF(update_op) +AST_END(update_op) + +AST_NODE(Update) + ast_ptr op; + ast_ptr value; +AST_END(Update) + +AST_LEAF(BinaryOperator) +AST_END(BinaryOperator) + +class Chain_t; + +AST_NODE(Assignable) + ast_ptr item; // Chain_t | Name_t | SelfName_t +AST_END(Assignable) + +class Value_t; + +AST_NODE(exp_op_value) + ast_ptr op; + ast_ptr value; +AST_END(exp_op_value) + +AST_NODE(Exp) + ast_ptr value; + ast_list opValues; +AST_END(Exp) + +AST_NODE(Callable) + ast_ptr item; // Name_t | SelfName_t | VarArg_t | Parens_t +AST_END(Callable) + +class InvokeArgs_t; + +AST_NODE(ChainValue) + ast_ptr caller; // Chain_t | Callable_t + ast_ptr arguments; +AST_END(ChainValue) + +class KeyValue_t; + +AST_NODE(simple_table) + ast_ptr sep; + ast_list pairs; +AST_END(simple_table) + +class String_t; + +AST_NODE(SimpleValue) + ast_ptr value; /* + const_value_t | + If_t | Unless_t | Switch_t | With_t | ClassDecl_t | ForEach_t | For_t | While_t | Do_t | + unary_exp_t | + TblComprehension_t | TableLit_t | Comprehension_t | FunLit_t | Num_t; + */ +AST_END(SimpleValue) + +AST_NODE(Chain) + ast_ptr item; // chain_call_t | chain_item_t | chain_dot_chain_t | ColonChain_t +AST_END(Chain) + +AST_NODE(Value) + ast_ptr item; // SimpleValue_t | simple_table_t | ChainValue_t | String_t + ast_node* getFlattened(); +AST_END(Value) + +AST_LEAF(LuaString) +AST_END(LuaString) + +AST_LEAF(SingleString) +AST_END(SingleString) + +AST_LEAF(double_string_inner) +AST_END(double_string_inner) + +AST_NODE(double_string_content) + ast_ptr content; // double_string_inner_t | Exp_t +AST_END(double_string_content) + +AST_NODE(DoubleString) + ast_ptr sep; + ast_list segments; +AST_END(DoubleString) + +AST_NODE(String) + ast_ptr str; // DoubleString_t | SingleString_t | LuaString_t +AST_END(String) + +AST_NODE(Parens) + ast_ptr expr; +AST_END(Parens) + +AST_NODE(FnArgs) + ast_ptr sep; + ast_list args; +AST_END(FnArgs) + +class ChainItems_t; + +AST_NODE(chain_call) + ast_ptr caller; // Callable_t | String_t + ast_ptr chain; +AST_END(chain_call) + +AST_NODE(chain_item) + ast_ptr chain; +AST_END(chain_item) + +AST_NODE(DotChainItem) + ast_ptr<_Name_t> name; +AST_END(DotChainItem) + +AST_NODE(ColonChainItem) + ast_ptr<_Name_t> name; +AST_END(ColonChainItem) + +AST_NODE(chain_dot_chain) + ast_ptr caller; + ast_ptr chain; +AST_END(chain_dot_chain) + +class ColonChain_t; +class Invoke_t; +class Slice_t; + +AST_NODE(ChainItem) + ast_ptr item; // Invoke_t | DotChainItem_t | Slice_t | [Exp_t] +AST_END(ChainItem) + +AST_NODE(ChainItems) + ast_ptr sep; + ast_list simpleChain; + ast_ptr colonChain; +AST_END(ChainItems) + +AST_NODE(invoke_chain) + ast_ptr invoke; + ast_ptr chain; +AST_END(invoke_chain) + +AST_NODE(ColonChain) + ast_ptr colonChain; + ast_ptr invokeChain; +AST_END(ColonChain) + +AST_LEAF(default_value) +AST_END(default_value) + +AST_NODE(Slice) + ast_ptr startValue; // Exp_t | default_value_t + ast_ptr stopValue; // Exp_t | default_value_t + ast_ptr stepValue; // Exp_t | default_value_t +AST_END(Slice) + +AST_NODE(Invoke) + ast_ptr argument; // FnArgs_t | SingleString_t | DoubleString_t | LuaString_t +AST_END(Invoke) + +class KeyValue_t; + +AST_NODE(TableValue) + ast_ptr value; // KeyValue_t | Exp_t +AST_END(TableValue) + +AST_NODE(TableLit) + ast_ptr sep; + ast_list values; +AST_END(TableLit) + +AST_NODE(TableBlock) + ast_ptr sep; + ast_list values; +AST_END(TableBlock) + +AST_NODE(class_member_list) + ast_ptr sep; + ast_list values; +AST_END(class_member_list) + +AST_NODE(ClassLine) + ast_ptr content; // class_member_list_t | Statement_t | Exp_t +AST_END(ClassLine) + +AST_NODE(ClassBlock) + ast_ptr sep; + ast_list lines; +AST_END(ClassBlock) + +AST_NODE(ClassDecl) + ast_ptr name; + ast_ptr extend; + ast_ptr body; +AST_END(ClassDecl) + +AST_NODE(export_values) + ast_ptr nameList; + ast_ptr valueList; +AST_END(export_values) + +AST_LEAF(export_op) +AST_END(export_op) + +AST_NODE(Export) + ast_ptr item; // ClassDecl_t | export_op_t | export_values_t +AST_END(Export) + +AST_NODE(variable_pair) + ast_ptr name; +AST_END(variable_pair) + +AST_NODE(normal_pair) + ast_ptr key; // KeyName_t | [Exp_t] | DoubleString_t | SingleString_t + ast_ptr value; // Exp_t | TableBlock_t +AST_END(normal_pair) + +AST_NODE(KeyValue) + ast_ptr item; // variable_pair_t | normal_pair_t +AST_END(KeyValue) + +AST_NODE(FnArgDef) + ast_ptr name; // Name_t | SelfName_t + ast_ptr defaultValue; +AST_END(FnArgDef) + +AST_NODE(FnArgDefList) + ast_ptr sep; + ast_list definitions; + ast_ptr varArg; +AST_END(FnArgDefList) + +AST_NODE(outer_var_shadow) + ast_ptr varList; +AST_END(outer_var_shadow) + +AST_NODE(FnArgsDef) + ast_ptr defList; + ast_ptr shadowOption; +AST_END(FnArgsDef) + +AST_LEAF(fn_arrow) +AST_END(fn_arrow) + +AST_NODE(FunLit) + ast_ptr argsDef; + ast_ptr arrow; + ast_ptr body; +AST_END(FunLit) + +AST_NODE(NameOrDestructure) + ast_ptr item; // Name_t | TableLit_t +AST_END(NameOrDestructure) + +AST_NODE(AssignableNameList) + ast_ptr sep; + ast_list items; +AST_END(AssignableNameList) + +AST_NODE(ArgBlock) + ast_ptr sep; + ast_list arguments; +AST_END(ArgBlock) + +AST_NODE(invoke_args_with_table) + ast_ptr argBlock; + ast_ptr tableBlock; +AST_END(invoke_args_with_table) + +AST_NODE(InvokeArgs) + ast_ptr argsList; + ast_ptr argsTableBlock; + ast_ptr tableBlock; +AST_END(InvokeArgs) + +AST_LEAF(const_value) +AST_END(const_value) + +AST_NODE(unary_exp) + ast_ptr item; +AST_END(unary_exp) + +AST_NODE(Assignment) + ast_ptr assignable; + ast_ptr target; // Update_t | Assign_t +AST_END(Assignment) + +AST_NODE(if_else_line) + ast_ptr condition; + ast_ptr elseExpr; // Exp_t | default_value_t +AST_END(if_else_line) + +AST_NODE(unless_line) + ast_ptr condition; +AST_END(unless_line) + +AST_NODE(statement_appendix) + ast_ptr item; // if_else_line_t | unless_line_t | CompInner_t +AST_END(statement_appendix) + +AST_LEAF(BreakLoop) +AST_END(BreakLoop) + +AST_NODE(Statement) + ast_ptr content; /* + Import_t | While_t | With_t | For_t | ForEach_t | + Switch_t | Return_t | Local_t | Export_t | BreakLoop_t | + Assignment_t | ExpList_t + */ + ast_ptr appendix; +AST_END(Statement) + +class Block_t; + +AST_NODE(Body) + ast_ptr content; // Block | Statement +AST_END(Body) + +AST_NODE(Line) + ast_ptr statment; +AST_END(Line) + +AST_NODE(Block) + ast_ptr sep; + ast_list lines; +AST_END(Block) + +AST_NODE(BlockEnd) + ast_ptr block; +AST_END(BlockEnd) diff --git a/MoonParser/moon_parser.cpp b/MoonParser/moon_parser.cpp new file mode 100644 index 0000000..3069659 --- /dev/null +++ b/MoonParser/moon_parser.cpp @@ -0,0 +1,508 @@ +#include "moon_parser.h" + +rule Any = any(); +rule plain_space = *set(" \t"); +rule Break = nl(-expr('\r') >> '\n'); +rule White = *(set(" \t") | Break); +rule Stop = Break | eof(); +rule Comment = "--" >> *(not_(set("\r\n")) >> Any) >> and_(Stop); +rule Indent = *set(" \t"); +rule Space = plain_space >> -Comment; +rule SomeSpace = +set(" \t") >> -Comment; +rule SpaceBreak = Space >> Break; +rule EmptyLine = SpaceBreak; +rule AlphaNum = range('a', 'z') | range('A', 'Z') | range('0', '9') | '_'; +rule _Name = (range('a', 'z') | range('A', 'Z') | '_') >> *AlphaNum; +rule SpaceName = Space >> _Name; +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") + ) | ( + ( + (+range('0', '9') >> -('.' >> +range('0', '9'))) | + ('.' >> +range('0', '9')) + ) >> -(set("eE") >> -expr('-') >> +range('0', '9')) + ); +rule Num = Space >> _Num; +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)) +#define opWord(str) (Space >> str >> not_(AlphaNum)) +#define op(str) (Space >> str) + +rule Name = user(SpaceName, [](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); + std::string name; + st->buffer >> name; + st->buffer.str(""); + st->buffer.clear(); + auto it = st->keywords.find(name); + return it == st->keywords.end(); +}); + +rule self = expr('@'); +rule self_name = '@' >> _Name; +rule self_class = expr("@@"); +rule self_class_name = "@@" >> _Name; + +rule SelfName = Space >> (self_class_name | self_class | self_name | self); +rule KeyName = SelfName | Space >> _Name; +rule VarArg = Space >> "..."; + +rule check_indent = user(Indent, [](const item_t& item) +{ + int indent = 0; + for (input_it i = item.begin; i != item.end; ++i) + { + switch (*i) + { + case ' ': indent++; break; + case '\t': indent += 4; break; + } + } + State* st = reinterpret_cast(item.user_data); + return st->indents.top() == indent; +}); +rule CheckIndent = and_(check_indent); + +rule advance = user(Indent, [](const item_t& item) +{ + int indent = 0; + for (input_it i = item.begin; i != item.end; ++i) + { + switch (*i) + { + case ' ': indent++; break; + case '\t': indent += 4; break; + } + } + State* st = reinterpret_cast(item.user_data); + int top = st->indents.top(); + if (top != -1 && indent > top) + { + st->indents.push(indent); + return true; + } + return false; +}); +rule Advance = and_(advance); + +rule push_indent = user(Indent, [](const item_t& item) +{ + int indent = 0; + for (input_it i = item.begin; i != item.end; ++i) + { + switch (*i) + { + case ' ': indent++; break; + case '\t': indent += 4; break; + } + } + State* st = reinterpret_cast(item.user_data); + st->indents.push(indent); + return true; +}); +rule PushIndent = and_(push_indent); + +rule PreventIndent = user(true_(), [](const item_t& item) +{ + State* st = reinterpret_cast(item.user_data); + st->indents.push(-1); + return true; +}); + +rule PopIndent = user(true_(), [](const item_t& item) +{ + State* st = reinterpret_cast(item.user_data); + st->indents.pop(); + return true; +}); + +extern rule Block; + +rule InBlock = Advance >> Block >> PopIndent; + +extern rule NameList; + +rule local_flag = op('*') | op('^'); +rule Local = key("local") >> (local_flag | NameList); + +rule colon_import_name = sym('\\') >> Name; +rule ImportName = colon_import_name | Name; +rule ImportNameList = Seperator >> *SpaceBreak >> ImportName >> *((+SpaceBreak | sym(',') >> *SpaceBreak) >> ImportName); + +extern rule Exp; + +rule Import = key("import") >> ImportNameList >> *SpaceBreak >> key("from") >> Exp; +rule BreakLoop = key("break") | key("continue"); + +extern rule ExpListLow, ExpList, Assign; + +rule Return = key("return") >> -ExpListLow; +rule WithExp = ExpList >> -Assign; + +extern rule DisableDo, PopDo, Body; + +rule With = key("with") >> DisableDo >> ensure(WithExp, PopDo) >> -key("do") >> Body; +rule SwitchCase = key("when") >> ExpList >> -key("then") >> Body; +rule SwitchElse = key("else") >> Body; + +rule SwitchBlock = *EmptyLine >> + Advance >> Seperator >> + SwitchCase >> + *(+Break >> SwitchCase) >> + -(+Break >> SwitchElse) >> + PopIndent; + +rule Switch = key("switch") >> + DisableDo >> ensure(Exp, PopDo) >> + -key("do") >> -Space >> Break >> SwitchBlock; + +rule IfCond = Exp >> -Assign; +rule IfElseIf = -(Break >> *EmptyLine >> CheckIndent) >> key("elseif") >> IfCond >> -key("then") >> Body; +rule IfElse = -(Break >> *EmptyLine >> CheckIndent) >> key("else") >> Body; +rule If = key("if") >> IfCond >> -key("then") >> Body >> Seperator >> *IfElseIf >> -IfElse; +rule Unless = key("unless") >> IfCond >> -key("then") >> Body >> Seperator >> *IfElseIf >> -IfElse; + +rule While = key("while") >> DisableDo >> ensure(Exp, PopDo) >> -key("do") >> Body; + +rule for_step_value = sym(',') >> Exp; +rule for_args = Name >> sym('=') >> Exp >> sym(',') >> Exp >> -for_step_value; + +rule For = key("for") >> DisableDo >> + ensure(for_args, PopDo) >> + -key("do") >> Body; + +extern rule AssignableNameList; + +rule for_in = sym('*') >> Exp | ExpList; + +rule ForEach = key("for") >> AssignableNameList >> key("in") >> + DisableDo >> ensure(for_in, PopDo) >> + -key("do") >> Body; + +rule Do = user(key("do") >> Body, [](const item_t& item) +{ + State* st = reinterpret_cast(item.user_data); + return st->doStack.empty() || st->doStack.top(); +}); + +rule DisableDo = user(true_(), [](const item_t& item) +{ + State* st = reinterpret_cast(item.user_data); + st->doStack.push(false); + return true; +}); + +rule PopDo = user(true_(), [](const item_t& item) +{ + State* st = reinterpret_cast(item.user_data); + st->doStack.pop(); + return true; +}); + +extern rule CompInner; + +rule Comprehension = sym('[') >> Exp >> CompInner >> sym(']'); +rule comp_value = sym(',') >> Exp; +rule TblComprehension = sym('{') >> (Exp >> -comp_value) >> CompInner >> sym('}'); + +extern rule CompForEach, CompFor, CompClause; + +rule CompInner = (CompForEach | CompFor) >> Seperator >> *CompClause; +rule star_exp = sym('*') >> Exp; +rule CompForEach = key("for") >> AssignableNameList >> key("in") >> (star_exp | Exp); +rule CompFor = key("for") >> Name >> sym('=') >> Exp >> sym(',') >> Exp >> -for_step_value; +rule CompClause = CompFor | CompForEach | key("when") >> Exp; + +extern rule TableBlock; + +rule Assign = sym('=') >> (With | If | Switch | TableBlock | ExpListLow); + +rule update_op = + sym("..=") | + sym("+=") | + sym("-=") | + sym("*=") | + sym("/=") | + sym("%=") | + sym("or=") | + sym("and=") | + sym("&=") | + sym("|=") | + sym(">>=") | + sym("<<="); + +rule Update = update_op >> Exp; + +rule CharOperators = Space >> set("+-*/%^><|&"); +rule WordOperators = + opWord("or") | + opWord("and") | + op("<=") | + op(">=") | + op("~=") | + op("!=") | + op("==") | + op("..") | + op("<<") | + op(">>") | + op("//"); + +rule BinaryOperator = (WordOperators | CharOperators) >> *SpaceBreak; + +extern rule Chain; + +rule Assignable = Chain | Name | SelfName; + +extern rule Value; + +rule exp_op_value = BinaryOperator >> Value; +rule Exp = Value >> *exp_op_value; + +extern rule Callable, InvokeArgs; + +rule ChainValue = (Chain | Callable) >> -InvokeArgs; + +extern rule KeyValue, String, SimpleValue; + +rule simple_table = Seperator >> KeyValue >> *(sym(',') >> KeyValue); +rule Value = SimpleValue | simple_table | ChainValue | String; + +extern rule LuaString; + +rule single_string_inner = expr("\\'") | "\\\\" | not_(expr('\'')) >> Any; +rule SingleString = symx('\'') >> *single_string_inner >> sym('\''); +rule interp = symx("#{") >> Exp >> sym('}'); +rule double_string_plain = expr("\\\"") | "\\\\" | not_(expr('"')) >> Any; +rule double_string_inner = +(not_(interp) >> double_string_plain); +rule double_string_content = double_string_inner | interp; +rule DoubleString = symx('"') >> Seperator >> *double_string_content >> sym('"'); +rule String = Space >> (DoubleString | SingleString | LuaString); + +rule lua_string_open = '[' >> *expr('=') >> '['; +rule lua_string_close = ']' >> *expr('=') >> ']'; + +rule LuaStringOpen = user(lua_string_open, [](const item_t& item) +{ + size_t count = std::distance(item.begin, item.end); + State* st = reinterpret_cast(item.user_data); + st->stringOpen = count; + return true; +}); + +rule LuaStringClose = user(lua_string_close, [](const item_t& item) +{ + size_t count = std::distance(item.begin, item.end); + State* st = reinterpret_cast(item.user_data); + return st->stringOpen == count; +}); + +rule LuaStringContent = *(not_(LuaStringClose) >> (Break | Any)); + +rule LuaString = user(LuaStringOpen >> -Break >> LuaStringContent >> LuaStringClose, [](const item_t& item) +{ + State* st = reinterpret_cast(item.user_data); + st->stringOpen = -1; + return true; +}); + +rule Parens = sym('(') >> *SpaceBreak >> Exp >> *SpaceBreak >> sym(')'); +rule Callable = Name | SelfName | VarArg | Parens; +rule FnArgsExpList = Exp >> *((Break | sym(',')) >> White >> Exp); + +rule FnArgs = Seperator >> +( + ( + symx('(') >> *SpaceBreak >> -FnArgsExpList >> *SpaceBreak >> sym(')') + ) | ( + sym('!') >> not_(expr('=')) + ) +); + +extern rule ChainItems, DotChainItem, ColonChain; + +rule chain_call = (Callable | String) >> ChainItems; +rule chain_item = not_(set(".\\")) >> ChainItems; +rule chain_dot_chain = DotChainItem >> -ChainItems; + +rule Chain = + chain_call | + chain_item | + Space >> (chain_dot_chain | ColonChain); + +extern rule ChainItem; + +rule chain_with_colon = +ChainItem >> -ColonChain; +rule ChainItems = Seperator >> (chain_with_colon | ColonChain); + +extern rule Invoke, Slice; + +rule Index = symx('[') >> Exp >> sym(']'); +rule ChainItem = Invoke | DotChainItem | Slice | Index; +rule DotChainItem = symx('.') >> _Name; +rule ColonChainItem = symx('\\') >> _Name; +rule invoke_chain = Invoke >> -ChainItems; +rule ColonChain = ColonChainItem >> -invoke_chain; + +rule default_value = true_(); +rule Slice = + symx('[') >> + (Exp | default_value) >> + sym(',') >> + (Exp | default_value) >> + (sym(',') >> Exp | default_value) >> + sym(']'); + +rule Invoke = + FnArgs | + SingleString | + DoubleString | + and_(expr('[')) >> LuaString; + +extern rule TableValueList, TableLitLine; + +rule TableValue = KeyValue | Exp; + +rule table_lit_lines = SpaceBreak >> TableLitLine >> *(-sym(',') >> SpaceBreak >> TableLitLine) >> -sym(','); + +rule TableLit = + sym('{') >> Seperator >> + -TableValueList >> + -sym(',') >> + -table_lit_lines >> + White >> sym('}'); + +rule TableValueList = TableValue >> *(sym(',') >> TableValue); + +rule TableLitLine = +( + PushIndent >> (TableValueList >> PopIndent | PopIndent) +) | ( + Space +); + +extern rule KeyValueLine; + +rule TableBlockInner = Seperator >> KeyValueLine >> *(+(SpaceBreak) >> KeyValueLine); +rule TableBlock = +(SpaceBreak) >> Advance >> ensure(TableBlockInner, PopIndent); + +extern rule Statement; + +rule class_member_list = Seperator >> KeyValue >> *(sym(',') >> KeyValue); +rule ClassLine = CheckIndent >> (class_member_list | Statement | Exp) >> -sym(','); +rule ClassBlock = +(SpaceBreak) >> Advance >>Seperator >> ClassLine >> *(+(SpaceBreak) >> ClassLine) >> PopIndent; + +rule ClassDecl = + key("class") >> not_(expr(':')) >> + -Assignable >> + -(key("extends") >> PreventIndent >> ensure(Exp, PopIndent)) >> + -ClassBlock; + +rule export_values = NameList >> -(sym('=') >> ExpListLow); +rule export_op = op('*') | op('^'); +rule Export = key("export") >> (ClassDecl | export_op | export_values); + +rule variable_pair = sym(':') >> not_(SomeSpace) >> Name; + +rule normal_pair = +( + KeyName | + sym('[') >> Exp >> sym(']') | + Space >> DoubleString | + Space >> SingleString +) >> +symx(':') >> +(Exp | TableBlock | +(SpaceBreak) >> Exp); + +rule KeyValue = variable_pair | normal_pair; + +rule KeyValueList = KeyValue >> *(sym(',') >> KeyValue); +rule KeyValueLine = CheckIndent >> KeyValueList >> -sym(','); + +rule FnArgDef = (Name | SelfName) >> -(sym('=') >> Exp); + +rule FnArgDefList = Seperator >> +( + ( + FnArgDef >> + *((sym(',') | Break) >> White >> FnArgDef) >> + -((sym(',') | Break) >> White >> VarArg) + ) | ( + VarArg + ) +); + +rule outer_var_shadow = key("using") >> (NameList | Space >> expr("nil")); + +rule FnArgsDef = sym('(') >> White >> -FnArgDefList >> -outer_var_shadow >> White >> sym(')'); +rule fn_arrow = sym("->") | sym("=>"); +rule FunLit = -FnArgsDef >> fn_arrow >> -Body; + +rule NameList = Seperator >> Name >> *(sym(',') >> Name); +rule NameOrDestructure = Name | TableLit; +rule AssignableNameList = Seperator >> NameOrDestructure >> *(sym(',') >> NameOrDestructure); + +rule ExpList = Seperator >> Exp >> *(sym(',') >> Exp); +rule ExpListLow = Seperator >> Exp >> *((sym(',') | sym(';')) >> Exp); + +rule ArgLine = CheckIndent >> Exp >> *(sym(',') >> Exp); +rule ArgBlock = Seperator >> ArgLine >> *(sym(',') >> SpaceBreak >> ArgLine) >> PopIndent; + +rule invoke_args_with_table = + sym(',') >> + ( + TableBlock | + SpaceBreak >> Advance >> ArgBlock >> -TableBlock + ); + +rule InvokeArgs = + not_(expr('-')) >> + ( + ExpList >> -(invoke_args_with_table | TableBlock) | + TableBlock + ); + +rule const_value = key("nil") | key("true") | key("false"); +rule minus_exp = sym('-') >> not_(SomeSpace) >> Exp; +rule sharp_exp = sym('#') >> Exp; +rule tilde_exp = sym('~') >> Exp; +rule not_exp = key("not") >> Exp; +rule unary_exp = minus_exp | sharp_exp | tilde_exp | not_exp; + +rule SimpleValue = + const_value | + If | Unless | Switch | With | ClassDecl | ForEach | For | While | Do | + unary_exp | + TblComprehension | TableLit | Comprehension | FunLit | Num; + +rule Assignment = ExpList >> (Update | Assign); + +rule if_else_line = key("if") >> Exp >> (key("else") >> Exp | default_value); +rule unless_line = key("unless") >> Exp; + +rule statement_appendix = (if_else_line | unless_line | CompInner) >> Space; +rule Statement = +( + Import | While | With | For | ForEach | + Switch | Return | Local | Export | BreakLoop | + Assignment | ExpList +) >> 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 BlockEnd = Block >> eof(); diff --git a/MoonParser/moon_parser.h b/MoonParser/moon_parser.h new file mode 100644 index 0000000..0c3f427 --- /dev/null +++ b/MoonParser/moon_parser.h @@ -0,0 +1,31 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include "parserlib.hpp" +using namespace parserlib; + +struct State +{ + State() + { + indents.push(0); + stringOpen = -1; + } + std::stringstream buffer; + size_t stringOpen; + std::stack indents; + std::stack doStack; + std::unordered_set keywords = { + "and", "while", "else", "using", "continue", + "local", "not", "then", "return", "from", + "extends", "for", "do", "or", "export", + "class", "in", "unless", "when", "elseif", + "switch", "break", "if", "with", "import" + }; +}; -- cgit v1.2.3-55-g6feb