diff options
| author | Li Jin <dragon-fly@qq.com> | 2019-09-08 00:28:49 +0800 |
|---|---|---|
| committer | Li Jin <dragon-fly@qq.com> | 2019-09-08 00:28:49 +0800 |
| commit | fabc309a0a0a6f210a8a7ed8f0d1f8498971f409 (patch) | |
| tree | 0187faf6b0caf17d1767b5a01ea174704742ab6f /MoonParser/moon_ast.cpp | |
| parent | 5e3d082dd2ea31acf0cc722c19b78aa4ef6e6077 (diff) | |
| download | yuescript-fabc309a0a0a6f210a8a7ed8f0d1f8498971f409.tar.gz yuescript-fabc309a0a0a6f210a8a7ed8f0d1f8498971f409.tar.bz2 yuescript-fabc309a0a0a6f210a8a7ed8f0d1f8498971f409.zip | |
completing moonscript compiler with c++.
Diffstat (limited to 'MoonParser/moon_ast.cpp')
| -rw-r--r-- | MoonParser/moon_ast.cpp | 822 |
1 files changed, 766 insertions, 56 deletions
diff --git a/MoonParser/moon_ast.cpp b/MoonParser/moon_ast.cpp index 2a6ca61..4fb0212 100644 --- a/MoonParser/moon_ast.cpp +++ b/MoonParser/moon_ast.cpp | |||
| @@ -2,23 +2,15 @@ | |||
| 2 | #include <unordered_set> | 2 | #include <unordered_set> |
| 3 | #include <stack> | 3 | #include <stack> |
| 4 | #include <algorithm> | 4 | #include <algorithm> |
| 5 | #include <sstream> | ||
| 6 | #include <vector> | 5 | #include <vector> |
| 6 | #include <numeric> | ||
| 7 | #include <memory> | ||
| 8 | #include <array> | ||
| 9 | #include <sstream> | ||
| 10 | #include <string_view> | ||
| 11 | using namespace std::string_view_literals; | ||
| 7 | #include "moon_ast.h" | 12 | #include "moon_ast.h" |
| 8 | 13 | ||
| 9 | input& trim(input& s) | ||
| 10 | { | ||
| 11 | s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](input::value_type ch) | ||
| 12 | { | ||
| 13 | return !std::isspace(ch); | ||
| 14 | })); | ||
| 15 | s.erase(std::find_if(s.rbegin(), s.rend(), [](input::value_type ch) | ||
| 16 | { | ||
| 17 | return !std::isspace(ch); | ||
| 18 | }).base(), s.end()); | ||
| 19 | return s; | ||
| 20 | } | ||
| 21 | |||
| 22 | const input& AstLeaf::getValue() | 14 | const input& AstLeaf::getValue() |
| 23 | { | 15 | { |
| 24 | if (_value.empty()) | 16 | if (_value.empty()) |
| @@ -144,50 +136,768 @@ AST_IMPL(BlockEnd) | |||
| 144 | 136 | ||
| 145 | #include <iostream> | 137 | #include <iostream> |
| 146 | 138 | ||
| 147 | int main() | 139 | template<class T, class... Args> |
| 140 | inline std::unique_ptr<T> MakeUnique(Args&&... args) { | ||
| 141 | return std::unique_ptr<T>(new T(std::forward<Args>(args)...)); | ||
| 142 | } | ||
| 143 | |||
| 144 | inline std::string s(std::string_view sv) { | ||
| 145 | return std::string(sv); | ||
| 146 | } | ||
| 147 | |||
| 148 | class MoonCompliler | ||
| 148 | { | 149 | { |
| 149 | std::string s = R"TestCodesHere( | 150 | public: |
| 150 | thing = { var: 10, hello: "world", func: => @var } | 151 | void complile(const std::string& codes) { |
| 151 | import hello, \func from thing | 152 | input input = _converter.from_bytes(codes); |
| 152 | )TestCodesHere"; | 153 | error_list el; |
| 153 | input i = Converter{}.from_bytes(s); | 154 | BlockEnd_t* root = nullptr; |
| 154 | 155 | State st; | |
| 155 | error_list el; | 156 | if (parse(input, BlockEnd, el, root, &st)) { |
| 156 | BlockEnd_t* root = nullptr; | 157 | std::cout << "matched!\n"; |
| 157 | State st; | 158 | std::vector<std::string> out; |
| 158 | if (parse(i, BlockEnd, el, root, &st)) | 159 | root->eachChild([&](ast_node* node) { |
| 159 | { | 160 | switch (node->getId()) { |
| 160 | std::cout << "matched!\n"; | 161 | case "Block"_id: |
| 161 | int indent = 0; | 162 | pushScope(); |
| 162 | root->visit([&](ast_node* node) | 163 | transformBlock(node, out); |
| 163 | { | 164 | popScope(); |
| 164 | if (std::string("Seperator") != node->getName()) | 165 | break; |
| 165 | { | 166 | default: break; |
| 166 | indent++; | 167 | } |
| 167 | for (int i = 0; i < indent; i++) std::cout << " "; | 168 | }); |
| 168 | std::cout << "{" << node->getName() << "\n"; | 169 | std::string result; |
| 169 | } | 170 | if (out.size() == 1) { |
| 170 | return false; | 171 | result = std::move(out.front()); |
| 171 | }, [&](ast_node* node) | 172 | } else if (out.size() > 1) { |
| 172 | { | 173 | result = join(out, "\n"); |
| 173 | if (std::string("Seperator") != node->getName()) | 174 | } |
| 174 | { | 175 | std::cout << result << '\n'; |
| 175 | for (int i = 0; i < indent; i++) std::cout << " "; | 176 | } else { |
| 176 | std::cout << "}\n" ; | 177 | std::cout << "not matched!\n"; |
| 177 | indent--; | 178 | for (error_list::iterator it = el.begin(); it != el.end(); ++it) { |
| 178 | } | 179 | const error& err = *it; |
| 179 | return false; | 180 | std::cout << "line " << err.m_begin.m_line << ", col " << err.m_begin.m_col << ": syntax error\n"; |
| 180 | }); | 181 | } |
| 181 | } | 182 | } |
| 182 | else | 183 | } |
| 183 | { | 184 | |
| 184 | std::cout << "not matched!\n"; | 185 | private: |
| 185 | for (error_list::iterator it = el.begin(); it != el.end(); ++it) | 186 | Converter _converter; |
| 186 | { | 187 | std::ostringstream _buf; |
| 187 | const error& err = *it; | 188 | std::string _newLine = "\n"; |
| 188 | std::cout << "line " << err.m_begin.m_line << ", col " << err.m_begin.m_col << ": syntax error\n"; | 189 | std::vector<int> _lineTable; |
| 190 | struct Scope { | ||
| 191 | std::unique_ptr<std::unordered_set<std::string>> vars; | ||
| 192 | std::unique_ptr<std::unordered_set<std::string>> allows; | ||
| 193 | }; | ||
| 194 | std::vector<Scope> _scopes; | ||
| 195 | static const std::string Empty; | ||
| 196 | |||
| 197 | void pushScope() { | ||
| 198 | _scopes.emplace_back(); | ||
| 199 | _scopes.back().vars = MakeUnique<std::unordered_set<std::string>>(); | ||
| 200 | } | ||
| 201 | |||
| 202 | bool isDefined(const std::string& name, bool checkShadowScope = false) { | ||
| 203 | bool isDefined = false; | ||
| 204 | for (auto it = _scopes.rbegin(); it != _scopes.rend(); ++it) { | ||
| 205 | auto vars = it->vars.get(); | ||
| 206 | if (vars->find(name) != vars->end()) { | ||
| 207 | isDefined = true; | ||
| 208 | break; | ||
| 209 | } | ||
| 210 | if (checkShadowScope && it->allows) break; | ||
| 211 | } | ||
| 212 | return isDefined; | ||
| 213 | } | ||
| 214 | |||
| 215 | void markVarShadowed() { | ||
| 216 | auto& scope = _scopes.back(); | ||
| 217 | scope.allows = MakeUnique<std::unordered_set<std::string>>(); | ||
| 218 | } | ||
| 219 | |||
| 220 | void addToAllowList(const std::string& name) { | ||
| 221 | auto& scope = _scopes.back(); | ||
| 222 | scope.allows->insert(name); | ||
| 223 | } | ||
| 224 | |||
| 225 | void forceAddToScope(const std::string& name) { | ||
| 226 | auto& scope = _scopes.back(); | ||
| 227 | scope.vars->insert(name); | ||
| 228 | } | ||
| 229 | |||
| 230 | bool addToScope(const std::string& name) { | ||
| 231 | bool defined = false; | ||
| 232 | auto& scope = _scopes.back(); | ||
| 233 | decltype(scope.allows.get()) allows = nullptr; | ||
| 234 | for (auto it = _scopes.rbegin(); it != _scopes.rend(); ++it) { | ||
| 235 | if (it->allows) allows = it->allows.get(); | ||
| 236 | } | ||
| 237 | if (allows) { | ||
| 238 | bool shadowed = allows->find(name) == allows->end(); | ||
| 239 | defined = isDefined(name, shadowed); | ||
| 240 | } else { | ||
| 241 | defined = isDefined(name); | ||
| 242 | } | ||
| 243 | if (!defined) scope.vars->insert(name); | ||
| 244 | return !defined; | ||
| 245 | } | ||
| 246 | |||
| 247 | void popScope() { | ||
| 248 | _scopes.pop_back(); | ||
| 249 | } | ||
| 250 | |||
| 251 | const std::string nll(ast_node* node) { | ||
| 252 | _lineTable.push_back(node->m_begin.m_line); | ||
| 253 | return _newLine; | ||
| 254 | } | ||
| 255 | |||
| 256 | const std::string nlr(ast_node* node) { | ||
| 257 | _lineTable.push_back(node->m_end.m_line); | ||
| 258 | return _newLine; | ||
| 259 | } | ||
| 260 | |||
| 261 | std::string indent() { | ||
| 262 | return std::string(_scopes.size() - 1, '\t'); | ||
| 263 | } | ||
| 264 | |||
| 265 | std::string clearBuf() { | ||
| 266 | std::string str = _buf.str(); | ||
| 267 | _buf.str(""); | ||
| 268 | _buf.clear(); | ||
| 269 | return str; | ||
| 270 | } | ||
| 271 | |||
| 272 | std::string join(const std::vector<std::string>& items) { | ||
| 273 | if (items.empty()) return Empty; | ||
| 274 | else if (items.size() == 1) return items.front(); | ||
| 275 | return std::accumulate(items.begin()+1, items.end(), items.front(), | ||
| 276 | [&](const std::string& a, const std::string& b) { return a + b; }); | ||
| 277 | } | ||
| 278 | |||
| 279 | std::string join(const std::vector<std::string>& items, std::string_view sep) { | ||
| 280 | if (items.empty()) return Empty; | ||
| 281 | else if (items.size() == 1) return items.front(); | ||
| 282 | std::string sepStr = s(sep); | ||
| 283 | return std::accumulate(items.begin()+1, items.end(), items.front(), | ||
| 284 | [&](const std::string& a, const std::string& b) { return a + sepStr + b; }); | ||
| 285 | } | ||
| 286 | |||
| 287 | std::string toString(ast_node* node) { | ||
| 288 | auto str = _converter.to_bytes(std::u32string(node->m_begin.m_it, node->m_end.m_it)); | ||
| 289 | return trim(str); | ||
| 290 | } | ||
| 291 | |||
| 292 | void noop(ast_node* node, std::vector<std::string>& out) { | ||
| 293 | auto str = _converter.to_bytes(std::u32string(node->m_begin.m_it, node->m_end.m_it)); | ||
| 294 | out.push_back(s("<"sv) + node->getName() + s(">"sv) + trim(str)); | ||
| 295 | // out.push_back(trim(str)); | ||
| 296 | } | ||
| 297 | |||
| 298 | void noopnl(ast_node* node, std::vector<std::string>& out) { | ||
| 299 | auto str = _converter.to_bytes(std::u32string(node->m_begin.m_it, node->m_end.m_it)); | ||
| 300 | out.push_back(s("<"sv) + node->getName() + s(">"sv) + trim(str) + nll(node)); | ||
| 301 | // out.push_back(trim(str) + nll(node)); | ||
| 302 | } | ||
| 303 | |||
| 304 | void transformBlock(ast_node* block, std::vector<std::string>& out) { | ||
| 305 | std::vector<std::string> temp; | ||
| 306 | block->eachChild([&](ast_node* node) { | ||
| 307 | switch (node->getId()) { | ||
| 308 | case "Line"_id: transformLine(node, temp); break; | ||
| 309 | default: break; | ||
| 310 | } | ||
| 311 | }); | ||
| 312 | out.push_back(join(temp)); | ||
| 313 | } | ||
| 314 | |||
| 315 | void transformLine(ast_node* line, std::vector<std::string>& out) { | ||
| 316 | line->eachChild([&](ast_node* node) { | ||
| 317 | switch (node->getId()) { | ||
| 318 | case "Statement"_id: transformStatement(node, out); break; | ||
| 319 | default: break; | ||
| 320 | } | ||
| 321 | }); | ||
| 322 | } | ||
| 323 | |||
| 324 | void transformStatement(ast_node* statement, std::vector<std::string>& out) { | ||
| 325 | std::vector<std::string> temp; | ||
| 326 | auto transformContent = [&](ast_node* node, std::vector<std::string>& out) { | ||
| 327 | switch (node->getId()) { | ||
| 328 | case "Import"_id: transformImport(node, temp); break; | ||
| 329 | case "While"_id: transformWhile(node, temp); break; | ||
| 330 | case "With"_id: transformWith(node, temp); break; | ||
| 331 | case "For"_id: transformFor(node, temp); break; | ||
| 332 | case "ForEach"_id: transformForEach(node, temp); break; | ||
| 333 | case "Switch"_id: transformSwitch(node, temp); break; | ||
| 334 | case "Return"_id: transformReturn(node, temp); break; | ||
| 335 | case "Local"_id: transformLocal(node, temp); break; | ||
| 336 | case "Export"_id: transformExport(node, temp); break; | ||
| 337 | case "BreakLoop"_id: transformBreakLoop(node, temp); break; | ||
| 338 | case "Assignment"_id: transformAssignment(node, temp); break; | ||
| 339 | case "ExpList"_id: | ||
| 340 | transformExpList(node, temp); | ||
| 341 | temp.back() = indent() + temp.back() + nll(node); | ||
| 342 | break; | ||
| 343 | default: break; | ||
| 344 | } | ||
| 345 | }; | ||
| 346 | if (statement->getChildCount() > 1) { | ||
| 347 | pushScope(); | ||
| 348 | transformContent(statement->getChild(0), out); | ||
| 349 | popScope(); | ||
| 350 | transform_statement_appendix(statement->getChild(1), temp); | ||
| 351 | } else { | ||
| 352 | transformContent(statement->getChild(0), out); | ||
| 353 | } | ||
| 354 | switch (temp.size()) { | ||
| 355 | case 1: // body | ||
| 356 | out.push_back(std::move(temp.front())); | ||
| 357 | break; | ||
| 358 | case 2: // body, if | ||
| 359 | out.push_back(join({std::move(temp[1]), std::move(temp[0]), s("end"sv) + nlr(statement)})); | ||
| 360 | break; | ||
| 361 | case 3: // body, if, else | ||
| 362 | out.push_back(join({std::move(temp[1]), std::move(temp[0]), std::move(temp[2]), s("end"sv) + nlr(statement)})); | ||
| 363 | break; | ||
| 364 | } | ||
| 365 | } | ||
| 366 | |||
| 367 | void transform_statement_appendix(ast_node* appendix, std::vector<std::string>& out) { | ||
| 368 | appendix->eachChild([&](ast_node* node) { | ||
| 369 | switch (node->getId()) { | ||
| 370 | case "if_else_line"_id: transform_if_else_line(node, out); break; | ||
| 371 | case "unless_line"_id: transform_unless_line(node, out); break; | ||
| 372 | case "CompInner"_id: transformCompInner(node, out); break; | ||
| 373 | default: break; | ||
| 374 | } | ||
| 375 | }); | ||
| 376 | } | ||
| 377 | |||
| 378 | void transform_if_else_line(ast_node* if_else_line, std::vector<std::string>& out) { | ||
| 379 | std::vector<std::string> temp; | ||
| 380 | if_else_line->eachChild([&](ast_node* node) { | ||
| 381 | switch (node->getId()) { | ||
| 382 | case "Exp"_id: | ||
| 383 | pushScope(); | ||
| 384 | transformExp(node, temp); | ||
| 385 | popScope(); | ||
| 386 | break; | ||
| 387 | default: break; | ||
| 388 | } | ||
| 389 | }); | ||
| 390 | out.push_back(indent() + s("if "sv) + temp[0] + s(" then"sv) + nll(if_else_line)); | ||
| 391 | out.push_back(indent() + s("else "sv) + nll(if_else_line) + indent() + '\t' + temp[1] + nll(if_else_line)); | ||
| 392 | } | ||
| 393 | |||
| 394 | void transformAssignment(ast_node* assignment, std::vector<std::string>& out) { | ||
| 395 | std::vector<std::string> temp; | ||
| 396 | std::string preDefined; | ||
| 397 | assignment->eachChild([&](ast_node* node) { | ||
| 398 | switch (node->getId()) { | ||
| 399 | case "ExpList"_id: { | ||
| 400 | std::vector<std::string> preDefs; | ||
| 401 | std::vector<ast_node*> values; | ||
| 402 | node->traverse([&](ast_node* child) { | ||
| 403 | if (child->getId() == "Value"_id) { | ||
| 404 | auto target = child->getByPath({"ChainValue"_id, "Callable"_id, "Name"_id}); | ||
| 405 | if (target) { | ||
| 406 | auto name = toString(target); | ||
| 407 | if (addToScope(name)) { | ||
| 408 | preDefs.push_back(name); | ||
| 409 | } | ||
| 410 | } | ||
| 411 | return traversal::Return; | ||
| 412 | } | ||
| 413 | return traversal::Continue; | ||
| 414 | }); | ||
| 415 | if (!preDefs.empty()) { | ||
| 416 | preDefined = indent() + s("local "sv) + join(preDefs, ", "sv) + nll(node); | ||
| 417 | } | ||
| 418 | transformExpList(node, temp); | ||
| 419 | break; | ||
| 420 | } | ||
| 421 | case "Update"_id: transformUpdate(node, temp); break; | ||
| 422 | case "Assign"_id: transformAssign(node, temp); break; | ||
| 423 | default: break; | ||
| 424 | } | ||
| 425 | }); | ||
| 426 | out.push_back(preDefined + indent() + temp[0] + s(" = "sv) + temp[1] + nll(assignment)); | ||
| 427 | } | ||
| 428 | |||
| 429 | void transformExpList(ast_node* expList, std::vector<std::string>& out) { | ||
| 430 | std::vector<std::string> temp; | ||
| 431 | expList->eachChild([&](ast_node* node) { | ||
| 432 | switch (node->getId()) { | ||
| 433 | case "Exp"_id: transformExp(node, temp); break; | ||
| 434 | default: break; | ||
| 435 | } | ||
| 436 | }); | ||
| 437 | out.push_back(join(temp, ", "sv)); | ||
| 438 | } | ||
| 439 | |||
| 440 | void transformExpListLow(ast_node* expListLow, std::vector<std::string>& out) { | ||
| 441 | std::vector<std::string> temp; | ||
| 442 | expListLow->eachChild([&](ast_node* node) { | ||
| 443 | switch (node->getId()) { | ||
| 444 | case "Exp"_id: transformExp(node, temp); break; | ||
| 445 | default: break; | ||
| 446 | } | ||
| 447 | }); | ||
| 448 | out.push_back(join(temp, ", "sv)); | ||
| 449 | } | ||
| 450 | |||
| 451 | void transformAssign(ast_node* assign, std::vector<std::string>& out) { | ||
| 452 | assign->eachChild([&](ast_node* node) { | ||
| 453 | switch (node->getId()) { | ||
| 454 | case "With"_id: transformWith(node, out); break; | ||
| 455 | case "If"_id: transformIf(node, out); break; | ||
| 456 | case "Switch"_id: transformSwitch(node, out); break; | ||
| 457 | case "TableBlock"_id: transformTableBlock(node, out); break; | ||
| 458 | case "ExpListLow"_id: transformExpListLow(node, out); break; | ||
| 459 | default: break; | ||
| 460 | } | ||
| 461 | }); | ||
| 462 | } | ||
| 463 | |||
| 464 | void transformExp(ast_node* exp, std::vector<std::string>& out) { | ||
| 465 | std::vector<std::string> temp; | ||
| 466 | exp->eachChild([&](ast_node* node) { | ||
| 467 | switch (node->getId()) { | ||
| 468 | case "Value"_id: transformValue(node, temp); break; | ||
| 469 | case "exp_op_value"_id: transform_exp_op_value(node, temp); break; | ||
| 470 | default: break; | ||
| 471 | } | ||
| 472 | }); | ||
| 473 | out.push_back(join(temp, " "sv)); | ||
| 474 | } | ||
| 475 | |||
| 476 | void transform_exp_op_value(ast_node* exp_op_value, std::vector<std::string>& out) { | ||
| 477 | exp_op_value->eachChild([&](ast_node* node) { | ||
| 478 | switch (node->getId()) { | ||
| 479 | case "BinaryOperator"_id: transformBinaryOperator(node, out); break; | ||
| 480 | case "Value"_id: transformValue(node, out); break; | ||
| 481 | default: break; | ||
| 482 | } | ||
| 483 | }); | ||
| 484 | } | ||
| 485 | |||
| 486 | void transformValue(ast_node* value, std::vector<std::string>& out) { | ||
| 487 | value->eachChild([&](ast_node* node) { | ||
| 488 | switch (node->getId()) { | ||
| 489 | case "SimpleValue"_id: transformSimpleValue(node, out); break; | ||
| 490 | case "simple_table"_id: transform_simple_table(node, out); break; | ||
| 491 | case "ChainValue"_id: transformChainValue(node, out); break; | ||
| 492 | case "String"_id: transformString(node, out); break; | ||
| 493 | default: break; | ||
| 494 | } | ||
| 495 | }); | ||
| 496 | } | ||
| 497 | |||
| 498 | void transformChainValue(ast_node* chainValue, std::vector<std::string>& out) { | ||
| 499 | std::vector<std::string> temp; | ||
| 500 | bool hasInvokeArgs = false; | ||
| 501 | chainValue->eachChild([&](ast_node* node) { | ||
| 502 | switch (node->getId()) { | ||
| 503 | case "Chain"_id: transformChain(node, temp); break; | ||
| 504 | case "Callable"_id: transformCallable(node, temp); break; | ||
| 505 | case "InvokeArgs"_id: | ||
| 506 | hasInvokeArgs = true; | ||
| 507 | transformInvokeArgs(node, temp); | ||
| 508 | break; | ||
| 509 | default: break; | ||
| 510 | } | ||
| 511 | }); | ||
| 512 | out.push_back(hasInvokeArgs ? (temp[0] + s("("sv) + temp[1] + s(")"sv)) : temp[0]); | ||
| 513 | } | ||
| 514 | |||
| 515 | void transformCallable(ast_node* callable, std::vector<std::string>& out) { | ||
| 516 | callable->eachChild([&](ast_node* node) { | ||
| 517 | switch (node->getId()) { | ||
| 518 | case "Name"_id: transformName(node, out); break; | ||
| 519 | case "SelfName"_id: transformSelfName(node, out); break; | ||
| 520 | case "VarArg"_id: transformVarArg(node, out); break; | ||
| 521 | case "Parens"_id: transformParens(node, out); break; | ||
| 522 | default: break; | ||
| 523 | } | ||
| 524 | }); | ||
| 525 | } | ||
| 526 | |||
| 527 | void transformParens(ast_node* parans, std::vector<std::string>& out) { | ||
| 528 | std::vector<std::string> temp; | ||
| 529 | parans->eachChild([&](ast_node* node) { | ||
| 530 | switch (node->getId()) { | ||
| 531 | case "Exp"_id: transformExp(node, temp); break; | ||
| 532 | default: break; | ||
| 533 | } | ||
| 534 | }); | ||
| 535 | out.push_back(s("("sv) + temp.front() + s(")"sv)); | ||
| 536 | } | ||
| 537 | |||
| 538 | void transformSimpleValue(ast_node* simpleValue, std::vector<std::string>& out) { | ||
| 539 | simpleValue->eachChild([&](ast_node* node) { | ||
| 540 | switch (node->getId()) { | ||
| 541 | case "const_value"_id: transform_const_value(node, out); break; | ||
| 542 | case "If"_id: transformIf(node, out); break; | ||
| 543 | case "Switch"_id: transformSwitch(node, out); break; | ||
| 544 | case "With"_id: transformWith(node, out); break; | ||
| 545 | case "ClassDecl"_id: transformClassDecl(node, out); break; | ||
| 546 | case "ForEach"_id: transformForEach(node, out); break; | ||
| 547 | case "For"_id: transformFor(node, out); break; | ||
| 548 | case "While"_id: transformWhile(node, out); break; | ||
| 549 | case "Do"_id: transformDo(node, out); break; | ||
| 550 | case "unary_exp"_id: transform_unary_exp(node, out); break; | ||
| 551 | case "TblComprehension"_id: transformTblComprehension(node, out); break; | ||
| 552 | case "TableLit"_id: transformTableLit(node, out); break; | ||
| 553 | case "Comprehension"_id: transformComprehension(node, out); break; | ||
| 554 | case "FunLit"_id: transformFunLit(node, out); break; | ||
| 555 | case "Num"_id: transformNum(node, out); break; | ||
| 556 | default: break; | ||
| 557 | } | ||
| 558 | }); | ||
| 559 | } | ||
| 560 | |||
| 561 | void transformFunLit(ast_node* funLit, std::vector<std::string>& out) { | ||
| 562 | std::vector<std::string> temp; | ||
| 563 | bool isFatArrow = false; | ||
| 564 | bool hasArgsDef = false; | ||
| 565 | ast_node* body = nullptr; | ||
| 566 | pushScope(); | ||
| 567 | funLit->eachChild([&](ast_node* node) { | ||
| 568 | switch (node->getId()) { | ||
| 569 | case "FnArgsDef"_id: | ||
| 570 | hasArgsDef = true; | ||
| 571 | transformFnArgsDef(node, temp); | ||
| 572 | break; | ||
| 573 | case "fn_arrow"_id: | ||
| 574 | isFatArrow = toString(node) == "=>"sv; | ||
| 575 | break; | ||
| 576 | case "Body"_id: | ||
| 577 | transformBody(node, temp); | ||
| 578 | body = node; | ||
| 579 | break; | ||
| 580 | default: break; | ||
| 581 | } | ||
| 582 | }); | ||
| 583 | popScope(); | ||
| 584 | if (hasArgsDef) { | ||
| 585 | auto& args = temp[0]; | ||
| 586 | auto& initArgs = temp[1]; | ||
| 587 | auto& bodyCodes = temp[2]; | ||
| 588 | _buf << "function("sv << | ||
| 589 | (isFatArrow ? s("self"sv) + s(args.empty() ? ""sv : ", "sv) : Empty) << | ||
| 590 | args << ')' << nll(funLit) << | ||
| 591 | (initArgs.empty() ? Empty : initArgs) << | ||
| 592 | (body ? bodyCodes : Empty) << | ||
| 593 | indent() << "end"sv; | ||
| 594 | out.push_back(clearBuf()); | ||
| 595 | } else { | ||
| 596 | auto& bodyCodes = temp[0]; | ||
| 597 | out.push_back( | ||
| 598 | s("function()"sv) + nll(funLit) + | ||
| 599 | (body ? bodyCodes : Empty) + | ||
| 600 | indent() + s("end"sv) | ||
| 601 | ); | ||
| 189 | } | 602 | } |
| 190 | } | 603 | } |
| 191 | system("pause"); | 604 | |
| 605 | void transformBody(ast_node* body, std::vector<std::string>& out) { | ||
| 606 | body->eachChild([&](ast_node* node) { | ||
| 607 | switch (node->getId()) { | ||
| 608 | case "Block"_id: transformBlock(node, out); break; | ||
| 609 | case "Statement"_id: transformStatement(node, out); break; | ||
| 610 | default: break; | ||
| 611 | } | ||
| 612 | }); | ||
| 613 | } | ||
| 614 | |||
| 615 | void transformFnArgsDef(ast_node* argsDef, std::vector<std::string>& out) { | ||
| 616 | argsDef->eachChild([&](ast_node* node) { | ||
| 617 | switch (node->getId()) { | ||
| 618 | case "FnArgDefList"_id: transformFnArgDefList(node, out); break; | ||
| 619 | case "outer_var_shadow"_id: transform_outer_var_shadow(node, out); break; | ||
| 620 | default: break; | ||
| 621 | } | ||
| 622 | }); | ||
| 623 | } | ||
| 624 | |||
| 625 | void transform_outer_var_shadow(ast_node* shadow, std::vector<std::string>& out) { | ||
| 626 | markVarShadowed(); | ||
| 627 | shadow->eachChild([&](ast_node* node) { | ||
| 628 | switch (node->getId()) { | ||
| 629 | case "NameList"_id: | ||
| 630 | node->eachChild([&](ast_node* child) { | ||
| 631 | if (child->getId() == "Name"_id) { | ||
| 632 | this->addToAllowList(toString(child)); | ||
| 633 | } | ||
| 634 | }); | ||
| 635 | break; | ||
| 636 | default: break; | ||
| 637 | } | ||
| 638 | }); | ||
| 639 | } | ||
| 640 | |||
| 641 | void transformFnArgDefList(ast_node* argDefList, std::vector<std::string>& out) { | ||
| 642 | std::vector<std::vector<std::string>> argItems; | ||
| 643 | const int Name = 0; | ||
| 644 | const int AssignSelf = 1; | ||
| 645 | const int DefaultVal = 2; | ||
| 646 | argDefList->eachChild([&](ast_node* node) { | ||
| 647 | switch (node->getId()) { | ||
| 648 | case "FnArgDef"_id: { | ||
| 649 | argItems.emplace_back(2); | ||
| 650 | auto& arg = argItems.back(); | ||
| 651 | node->eachChild([&](ast_node* child) { | ||
| 652 | switch (child->getId()) { | ||
| 653 | case "Name"_id: arg[Name] = toString(child); break; | ||
| 654 | case "SelfName"_id: | ||
| 655 | child->eachChild([&](ast_node* inner) { | ||
| 656 | switch (inner->getId()) { | ||
| 657 | case "self_class_name"_id: | ||
| 658 | arg[Name] = toString(inner->getChild(0)); | ||
| 659 | arg[AssignSelf] = s("self.__class."sv) + arg.front(); | ||
| 660 | break; | ||
| 661 | case "self_class"_id: | ||
| 662 | arg[Name] = "self.__class"sv; | ||
| 663 | break; | ||
| 664 | case "self_name"_id: | ||
| 665 | arg[Name] = toString(inner->getChild(0)); | ||
| 666 | arg[AssignSelf] = s("self."sv) + arg.front(); | ||
| 667 | break; | ||
| 668 | case "self"_id: | ||
| 669 | arg[Name] = "self"sv; | ||
| 670 | break; | ||
| 671 | } | ||
| 672 | }); | ||
| 673 | break; | ||
| 674 | case "Exp"_id: transformExp(child, arg); break; | ||
| 675 | default: break; | ||
| 676 | } | ||
| 677 | }); | ||
| 678 | break; | ||
| 679 | } | ||
| 680 | case "VarArg"_id: | ||
| 681 | argItems.emplace_back(2); | ||
| 682 | argItems.back()[Name] = "..."sv; | ||
| 683 | break; | ||
| 684 | default: break; | ||
| 685 | } | ||
| 686 | }); | ||
| 687 | std::string varNames; | ||
| 688 | for (const auto& item : argItems) { | ||
| 689 | if (varNames.empty()) { | ||
| 690 | varNames = item[Name]; | ||
| 691 | } else { | ||
| 692 | varNames.append(s(", "sv) + item[Name]); | ||
| 693 | } | ||
| 694 | forceAddToScope(item[Name]); | ||
| 695 | } | ||
| 696 | for (const auto& item : argItems) { | ||
| 697 | if (item.size() == 3 && !item[DefaultVal].empty()) { | ||
| 698 | _buf << indent() << "if "sv << item[Name] << " == nil then"sv << nll(argDefList) << | ||
| 699 | indent() << '\t' << item[Name] << " = "sv << item[DefaultVal] << nll(argDefList) << | ||
| 700 | indent() << "end"sv << nll(argDefList); | ||
| 701 | } | ||
| 702 | } | ||
| 703 | std::string initCodes = clearBuf(); | ||
| 704 | std::vector<std::array<const std::string*, 2>> assignSelfVars; | ||
| 705 | for (const auto& item : argItems) { | ||
| 706 | if (!item[AssignSelf].empty()) { | ||
| 707 | assignSelfVars.push_back({&item[AssignSelf], &item[Name]}); | ||
| 708 | } | ||
| 709 | } | ||
| 710 | auto sjoin = [](const decltype(assignSelfVars)& items, int index) { | ||
| 711 | std::string result; | ||
| 712 | for (auto it = items.begin(); it != items.end(); ++it) { | ||
| 713 | if (result.empty()) result = *((*it)[index]); | ||
| 714 | else result.append(s(", "sv) + *((*it)[index])); | ||
| 715 | } | ||
| 716 | return result; | ||
| 717 | }; | ||
| 718 | std::string sleft = sjoin(assignSelfVars, 0); | ||
| 719 | std::string sright = sjoin(assignSelfVars, 1); | ||
| 720 | if (!assignSelfVars.empty()) { | ||
| 721 | initCodes.append(sleft + s(" = "sv) + sright + nll(argDefList)); | ||
| 722 | } | ||
| 723 | out.push_back(varNames); | ||
| 724 | out.push_back(initCodes); | ||
| 725 | } | ||
| 726 | |||
| 727 | void transformChain(ast_node* chain, std::vector<std::string>& out) { | ||
| 728 | chain->eachChild([&](ast_node* node) { | ||
| 729 | switch (node->getId()) { | ||
| 730 | case "chain_call"_id: transform_chain_call(node, out); break; | ||
| 731 | case "chain_item"_id: transform_chain_item(node, out); break; | ||
| 732 | case "chain_dot_chain"_id: transform_chain_dot_chain(node, out); break; | ||
| 733 | case "ColonChain"_id: transformColonChain(node, out); break; | ||
| 734 | default: break; | ||
| 735 | } | ||
| 736 | }); | ||
| 737 | } | ||
| 738 | |||
| 739 | void transform_chain_call(ast_node* chain_call, std::vector<std::string>& out) { | ||
| 740 | std::vector<std::string> temp; | ||
| 741 | chain_call->eachChild([&](ast_node* node) { | ||
| 742 | switch (node->getId()) { | ||
| 743 | case "Callable"_id: transformCallable(node, temp); break; | ||
| 744 | case "String"_id: transformString(node, temp); break; | ||
| 745 | case "ChainItems"_id: transformChainItems(node, temp); break; | ||
| 746 | default: break; | ||
| 747 | } | ||
| 748 | }); | ||
| 749 | out.push_back(join(temp)); | ||
| 750 | } | ||
| 751 | |||
| 752 | void transformChainItems(ast_node* chainItems, std::vector<std::string>& out) { | ||
| 753 | std::vector<std::string> temp; | ||
| 754 | chainItems->eachChild([&](ast_node* node) { | ||
| 755 | switch (node->getId()) { | ||
| 756 | case "ChainItem"_id: transformChainItem(node, temp); break; | ||
| 757 | case "ColonChain"_id: transformColonChain(node, temp); break; | ||
| 758 | default: break; | ||
| 759 | } | ||
| 760 | }); | ||
| 761 | out.push_back(join(temp)); | ||
| 762 | } | ||
| 763 | |||
| 764 | void transformChainItem(ast_node* chainItem, std::vector<std::string>& out) { | ||
| 765 | chainItem->eachChild([&](ast_node* node) { | ||
| 766 | switch (node->getId()) { | ||
| 767 | case "Invoke"_id: transformInvoke(node, out); break; | ||
| 768 | case "DotChainItem"_id: | ||
| 769 | out.push_back(s("."sv) + toString(node->getChild(0))); | ||
| 770 | break; | ||
| 771 | case "Slice"_id: transformSlice(node, out); break; | ||
| 772 | case "Exp"_id: | ||
| 773 | transformExp(node, out); | ||
| 774 | out.back() = s("["sv) + out.back() + s("]"sv); | ||
| 775 | break; | ||
| 776 | default: break; | ||
| 777 | } | ||
| 778 | }); | ||
| 779 | } | ||
| 780 | |||
| 781 | void transformInvoke(ast_node* invoke, std::vector<std::string>& out) { | ||
| 782 | invoke->eachChild([&](ast_node* node) { | ||
| 783 | switch (node->getId()) { | ||
| 784 | case "FnArgs"_id: transformFnArgs(node, out); break; | ||
| 785 | case "SingleString"_id: transformSingleString(node, out); break; | ||
| 786 | case "DoubleString"_id: transformDoubleString(node, out); break; | ||
| 787 | case "LuaString"_id: transformLuaString(node, out); break; | ||
| 788 | default: break; | ||
| 789 | } | ||
| 790 | }); | ||
| 791 | } | ||
| 792 | |||
| 793 | void transformFnArgs(ast_node* fnArgs, std::vector<std::string>& out) { | ||
| 794 | std::vector<std::string> temp; | ||
| 795 | fnArgs->eachChild([&](ast_node* node) { | ||
| 796 | switch (node->getId()) { | ||
| 797 | case "Exp"_id: transformExp(node, temp); break; | ||
| 798 | default: break; | ||
| 799 | } | ||
| 800 | }); | ||
| 801 | std::string args = join(temp, ", "); | ||
| 802 | out.push_back(args.empty() ? "()" : s("(") + args + ")"); | ||
| 803 | } | ||
| 804 | |||
| 805 | void transformColonChain(ast_node* colonChain, std::vector<std::string>& out) { | ||
| 806 | std::vector<std::string> temp; | ||
| 807 | colonChain->eachChild([&](ast_node* node) { | ||
| 808 | switch (node->getId()) { | ||
| 809 | case "ColonChainItem"_id: | ||
| 810 | temp.push_back(s(":"sv) + toString(node->getChild(0))); | ||
| 811 | break; | ||
| 812 | case "invoke_chain"_id: transform_invoke_chain(node, temp); break; | ||
| 813 | default: break; | ||
| 814 | } | ||
| 815 | }); | ||
| 816 | out.push_back(join(temp)); | ||
| 817 | } | ||
| 818 | |||
| 819 | void transform_invoke_chain(ast_node* invoke_chain, std::vector<std::string>& out) { | ||
| 820 | std::vector<std::string> temp; | ||
| 821 | invoke_chain->eachChild([&](ast_node* node) { | ||
| 822 | switch (node->getId()) { | ||
| 823 | case "Invoke"_id: transformInvoke(node, temp); break; | ||
| 824 | case "ChainItems"_id: transformChainItems(node, temp); break; | ||
| 825 | default: break; | ||
| 826 | } | ||
| 827 | }); | ||
| 828 | out.push_back(join(temp)); | ||
| 829 | } | ||
| 830 | |||
| 831 | void transformUpdate(ast_node* node, std::vector<std::string>& out) {noop(node, out);} | ||
| 832 | |||
| 833 | void transformImport(ast_node* node, std::vector<std::string>& out) {noopnl(node, out);} | ||
| 834 | void transformWhile(ast_node* node, std::vector<std::string>& out) {noopnl(node, out);} | ||
| 835 | void transformWith(ast_node* node, std::vector<std::string>& out) {noopnl(node, out);} | ||
| 836 | void transformIf(ast_node* node, std::vector<std::string>& out) {noopnl(node, out);} | ||
| 837 | void transformFor(ast_node* node, std::vector<std::string>& out) {noopnl(node, out);} | ||
| 838 | void transformForEach(ast_node* node, std::vector<std::string>& out) {noopnl(node, out);} | ||
| 839 | void transformSwitch(ast_node* node, std::vector<std::string>& out) {noopnl(node, out);} | ||
| 840 | void transformReturn(ast_node* node, std::vector<std::string>& out) {noopnl(node, out);} | ||
| 841 | void transformTableBlock(ast_node* node, std::vector<std::string>& out) {noopnl(node, out);} | ||
| 842 | void transformLocal(ast_node* node, std::vector<std::string>& out) {noopnl(node, out);} | ||
| 843 | void transformExport(ast_node* node, std::vector<std::string>& out) {noopnl(node, out);} | ||
| 844 | void transformBreakLoop(ast_node* node, std::vector<std::string>& out) {noopnl(node, out);} | ||
| 845 | void transform_unless_line(ast_node* node, std::vector<std::string>& out) {noop(node, out);} | ||
| 846 | void transformCompInner(ast_node* node, std::vector<std::string>& out) {noop(node, out);} | ||
| 847 | void transform_simple_table(ast_node* node, std::vector<std::string>& out) {noop(node, out);} | ||
| 848 | void transformString(ast_node* node, std::vector<std::string>& out) {noop(node, out);} | ||
| 849 | void transformInvokeArgs(ast_node* node, std::vector<std::string>& out) {noop(node, out);} | ||
| 850 | void transformName(ast_node* node, std::vector<std::string>& out) {noop(node, out);} | ||
| 851 | void transformSelfName(ast_node* node, std::vector<std::string>& out) {noop(node, out);} | ||
| 852 | void transform_const_value(ast_node* node, std::vector<std::string>& out) {noop(node, out);} | ||
| 853 | void transformClassDecl(ast_node* node, std::vector<std::string>& out) {noop(node, out);} | ||
| 854 | void transformDo(ast_node* node, std::vector<std::string>& out) {noop(node, out);} | ||
| 855 | void transform_unary_exp(ast_node* node, std::vector<std::string>& out) {noop(node, out);} | ||
| 856 | void transformTblComprehension(ast_node* node, std::vector<std::string>& out) {noop(node, out);} | ||
| 857 | void transformTableLit(ast_node* node, std::vector<std::string>& out) {noop(node, out);} | ||
| 858 | void transformComprehension(ast_node* node, std::vector<std::string>& out) {noop(node, out);} | ||
| 859 | void transformNum(ast_node* node, std::vector<std::string>& out) {noop(node, out);} | ||
| 860 | void transformVarArg(ast_node* node, std::vector<std::string>& out) {noop(node, out);} | ||
| 861 | void transformBinaryOperator(ast_node* node, std::vector<std::string>& out) {noop(node, out);} | ||
| 862 | void transform_chain_item(ast_node* node, std::vector<std::string>& out) {noop(node, out);} | ||
| 863 | void transform_chain_dot_chain(ast_node* node, std::vector<std::string>& out) {noop(node, out);} | ||
| 864 | void transformSlice(ast_node* node, std::vector<std::string>& out) {noop(node, out);} | ||
| 865 | void transformSingleString(ast_node* node, std::vector<std::string>& out) {noop(node, out);} | ||
| 866 | void transformDoubleString(ast_node* node, std::vector<std::string>& out) {noop(node, out);} | ||
| 867 | void transformLuaString(ast_node* node, std::vector<std::string>& out) {noop(node, out);} | ||
| 868 | }; | ||
| 869 | |||
| 870 | const std::string MoonCompliler::Empty; | ||
| 871 | |||
| 872 | int main() | ||
| 873 | { | ||
| 874 | std::string s = R"TestCodesHere(a = 998 | ||
| 875 | f, d = (-> | ||
| 876 | joop = 2302 + 567 | ||
| 877 | |||
| 878 | (hi, a, b = Vec2(100,200), c, d, ... using nil) -> | ||
| 879 | d = "中文" | ||
| 880 | hi = 1021 | ||
| 881 | |||
| 882 | a,b,c,d = 1,2,3,4 | ||
| 883 | |||
| 884 | hello[232], (5+5)[121], hello, x[99] = 100, 200, 300 | ||
| 885 | |||
| 886 | joop = 12), 123 if true else print("a",1,2)\abc(998).x | ||
| 887 | |||
| 888 | a, b = if hello | ||
| 889 | "hello" | ||
| 890 | else | ||
| 891 | "nothing", "yeah" | ||
| 892 | |||
| 893 | |||
| 894 | a, b = if hello | ||
| 895 | if yeah then "one", "two" else "mmhh" | ||
| 896 | else | ||
| 897 | print "the other" | ||
| 898 | "nothing", "yeah")TestCodesHere"; | ||
| 899 | |||
| 900 | MoonCompliler{}.complile(s); | ||
| 901 | |||
| 192 | return 0; | 902 | return 0; |
| 193 | } | 903 | } |
