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 | } |