From 2531792fa8da2a2f2ae218c43937f88028d26888 Mon Sep 17 00:00:00 2001 From: Li Jin Date: Wed, 19 Jul 2017 10:01:27 +0800 Subject: adding codes. --- MoonParser/moon_ast.cpp | 1659 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1659 insertions(+) create mode 100644 MoonParser/moon_ast.cpp (limited to 'MoonParser/moon_ast.cpp') diff --git a/MoonParser/moon_ast.cpp b/MoonParser/moon_ast.cpp new file mode 100644 index 0000000..1595220 --- /dev/null +++ b/MoonParser/moon_ast.cpp @@ -0,0 +1,1659 @@ +#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) + +AST_NODE(Exp) + ast_ptr value; + ast_list opValues; +AST_END(Exp) + +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 + { + Data* data = static_cast(ud); + for (Exp_t* expr : valueList->exprs.objects()) + { + } + ((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 + { + + } +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() + { + 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(); + 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); + } + } + 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; +} -- cgit v1.2.3-55-g6feb