aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLi Jin <dragon-fly@qq.com>2020-01-10 16:30:34 +0800
committerLi Jin <dragon-fly@qq.com>2020-01-10 16:30:34 +0800
commit52a6536103f46c26a3ba9b149b0fe7b40d524d8c (patch)
tree67e4759f8e1ea922079d0e162d84ecba5e558261 /src
parent975167856ed0b11c2ede03c6eb750ca4e4a6a7fc (diff)
downloadyuescript-52a6536103f46c26a3ba9b149b0fe7b40d524d8c.tar.gz
yuescript-52a6536103f46c26a3ba9b149b0fe7b40d524d8c.tar.bz2
yuescript-52a6536103f46c26a3ba9b149b0fe7b40d524d8c.zip
update.
Diffstat (limited to '')
-rw-r--r--src/MoonP/ast.cpp (renamed from MoonParser/ast.cpp)12
-rw-r--r--src/MoonP/ast.hpp (renamed from MoonParser/ast.hpp)58
-rw-r--r--src/MoonP/moon_ast.cpp (renamed from MoonParser/moon_ast.cpp)10
-rw-r--r--src/MoonP/moon_ast.h (renamed from MoonParser/moon_ast.h)12
-rw-r--r--src/MoonP/moon_compiler.cpp (renamed from MoonParser/moon_compiler.cpp)154
-rw-r--r--src/MoonP/moon_compiler.h39
-rw-r--r--src/MoonP/moon_parser.cpp (renamed from MoonParser/moon_parser.cpp)61
-rw-r--r--src/MoonP/moon_parser.h35
-rw-r--r--src/MoonP/parser.cpp (renamed from MoonParser/parser.cpp)23
-rw-r--r--src/MoonP/parser.hpp (renamed from MoonParser/parser.hpp)10
-rw-r--r--src/moonc.cpp178
11 files changed, 452 insertions, 140 deletions
diff --git a/MoonParser/ast.cpp b/src/MoonP/ast.cpp
index 6c86854..cda2339 100644
--- a/MoonParser/ast.cpp
+++ b/src/MoonP/ast.cpp
@@ -1,5 +1,15 @@
1/* Copyright (c) 2012, Achilleas Margaritis, modified by Jin Li
2All rights reserved.
3
4 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
5
6 Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
7 Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
8
9THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
10
1#include <cassert> 11#include <cassert>
2#include "ast.hpp" 12#include "MoonP/ast.hpp"
3 13
4 14
5namespace parserlib { 15namespace parserlib {
diff --git a/MoonParser/ast.hpp b/src/MoonP/ast.hpp
index b388e77..f2ef76c 100644
--- a/MoonParser/ast.hpp
+++ b/src/MoonP/ast.hpp
@@ -1,3 +1,13 @@
1/* Copyright (c) 2012, Achilleas Margaritis, modified by Jin Li
2All rights reserved.
3
4 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
5
6 Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
7 Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
8
9THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
10
1#pragma once 11#pragma once
2 12
3 13
@@ -5,7 +15,7 @@
5#include <list> 15#include <list>
6#include <stdexcept> 16#include <stdexcept>
7#include <type_traits> 17#include <type_traits>
8#include "parser.hpp" 18#include "MoonP/parser.hpp"
9 19
10 20
11namespace parserlib { 21namespace parserlib {
@@ -57,7 +67,7 @@ public:
57 from a node stack. 67 from a node stack.
58 @param st stack. 68 @param st stack.
59 */ 69 */
60 virtual void construct(ast_stack& st) {} 70 virtual void construct(ast_stack&) {}
61 71
62 /** interface for visiting AST tree use. 72 /** interface for visiting AST tree use.
63 */ 73 */
@@ -78,11 +88,9 @@ public:
78 88
79 virtual bool visitChild(const std::function<bool (ast_node*)>& func); 89 virtual bool visitChild(const std::function<bool (ast_node*)>& func);
80 90
81 virtual size_t getId() const { return "ast_node"_id; } 91 virtual size_t getId() const = 0;
82 92
83 virtual const char* getName() const { return "ast_node"; } 93 virtual int get_type() = 0;
84
85 virtual int get_type() { return ast_type<ast_node>(); }
86 94
87 template<class T> 95 template<class T>
88 inline ast_ptr<false, T> new_ptr() { 96 inline ast_ptr<false, T> new_ptr() {
@@ -151,10 +159,6 @@ public:
151 virtual traversal traverse(const std::function<traversal (ast_node*)>& func) override; 159 virtual traversal traverse(const std::function<traversal (ast_node*)>& func) override;
152 160
153 virtual bool visitChild(const std::function<bool (ast_node*)>& func) override; 161 virtual bool visitChild(const std::function<bool (ast_node*)>& func) override;
154
155 virtual size_t getId() const override { return "ast_container"_id; }
156
157 virtual const char* getName() const override { return "ast_container"; }
158private: 162private:
159 ast_member_vector m_members; 163 ast_member_vector m_members;
160 164
@@ -285,14 +289,14 @@ public:
285 // check the stack node 289 // check the stack node
286 if (st.empty()) { 290 if (st.empty()) {
287 if (!Required) return; 291 if (!Required) return;
288 throw std::logic_error("Invalid AST stack"); 292 throw std::logic_error("Invalid AST stack.");
289 } 293 }
290 ast_node* node = st.back(); 294 ast_node* node = st.back();
291 if (!ast_ptr::accept(node)) { 295 if (!ast_ptr::accept(node)) {
292 // if the object is not required, simply return 296 // if the object is not required, simply return
293 if (!Required) return; 297 if (!Required) return;
294 // else if the object is mandatory, throw an exception 298 // else if the object is mandatory, throw an exception
295 throw std::logic_error("Invalid AST node"); 299 throw std::logic_error("Invalid AST node.");
296 } 300 }
297 st.pop_back(); 301 st.pop_back();
298 m_ptr = node; 302 m_ptr = node;
@@ -327,12 +331,12 @@ public:
327 virtual void construct(ast_stack& st) override { 331 virtual void construct(ast_stack& st) override {
328 if (st.empty()) { 332 if (st.empty()) {
329 if (!Required) return; 333 if (!Required) return;
330 throw std::logic_error("Invalid AST stack"); 334 throw std::logic_error("Invalid AST stack.");
331 } 335 }
332 ast_node* node = st.back(); 336 ast_node* node = st.back();
333 if (!ast_sel::accept(node)) { 337 if (!ast_sel::accept(node)) {
334 if (!Required) return; 338 if (!Required) return;
335 throw std::logic_error("Invalid AST node"); 339 throw std::logic_error("Invalid AST node.");
336 } 340 }
337 st.pop_back(); 341 st.pop_back();
338 m_ptr = node; 342 m_ptr = node;
@@ -388,20 +392,6 @@ public:
388 node->release(); 392 node->release();
389 } 393 }
390 394
391 void set_front(ast_node* node) {
392 assert(node && accept(node));
393 m_objects.front()->release();
394 m_objects.front() = node;
395 node->retain();
396 }
397
398 void set_back(ast_node* node) {
399 assert(node && accept(node));
400 m_objects.back()->release();
401 m_objects.back() = node;
402 node->retain();
403 }
404
405 const node_container& objects() const { 395 const node_container& objects() const {
406 return m_objects; 396 return m_objects;
407 } 397 }
@@ -455,7 +445,7 @@ public:
455 // end the list parsing 445 // end the list parsing
456 if (!ast_list::accept(node)) { 446 if (!ast_list::accept(node)) {
457 if (Required && m_objects.empty()) { 447 if (Required && m_objects.empty()) {
458 throw std::logic_error("Invalid AST node"); 448 throw std::logic_error("Invalid AST node.");
459 } 449 }
460 return; 450 return;
461 } 451 }
@@ -465,7 +455,7 @@ public:
465 node->retain(); 455 node->retain();
466 } 456 }
467 if (Required && m_objects.empty()) { 457 if (Required && m_objects.empty()) {
468 throw std::logic_error("Invalid AST stack"); 458 throw std::logic_error("Invalid AST stack.");
469 } 459 }
470 } 460 }
471private: 461private:
@@ -493,7 +483,7 @@ public:
493 ast_node* node = st.back(); 483 ast_node* node = st.back();
494 if (!ast_sel_list::accept(node)) { 484 if (!ast_sel_list::accept(node)) {
495 if (Required && m_objects.empty()) { 485 if (Required && m_objects.empty()) {
496 throw std::logic_error("Invalid AST node"); 486 throw std::logic_error("Invalid AST node.");
497 } 487 }
498 return; 488 return;
499 } 489 }
@@ -502,7 +492,7 @@ public:
502 node->retain(); 492 node->retain();
503 } 493 }
504 if (Required && m_objects.empty()) { 494 if (Required && m_objects.empty()) {
505 throw std::logic_error("Invalid AST stack"); 495 throw std::logic_error("Invalid AST stack.");
506 } 496 }
507 } 497 }
508private: 498private:
@@ -548,7 +538,7 @@ private:
548 @return pointer to ast node created, or null if there was an error. 538 @return pointer to ast node created, or null if there was an error.
549 The return object must be deleted by the caller. 539 The return object must be deleted by the caller.
550 */ 540 */
551ast_node* _parse(input &i, rule &g, error_list &el, void* ud); 541ast_node* _parse(input& i, rule& g, error_list& el, void* ud);
552 542
553 543
554/** parses the given input. 544/** parses the given input.
@@ -558,7 +548,7 @@ ast_node* _parse(input &i, rule &g, error_list &el, void* ud);
558 @param ud user data, passed to the parse procedures. 548 @param ud user data, passed to the parse procedures.
559 @return ast nodes. 549 @return ast nodes.
560 */ 550 */
561template <class T> ast_ptr<false, T> parse(input &i, rule &g, error_list &el, void* ud = nullptr) { 551template <class T> ast_ptr<false, T> parse(input& i, rule& g, error_list& el, void* ud = nullptr) {
562 ast_node* node = _parse(i, g, el, ud); 552 ast_node* node = _parse(i, g, el, ud);
563 T* ast = ast_cast<T>(node); 553 T* ast = ast_cast<T>(node);
564 ast_ptr<false, T> ptr; 554 ast_ptr<false, T> ptr;
diff --git a/MoonParser/moon_ast.cpp b/src/MoonP/moon_ast.cpp
index 6b175fc..0ccd0ed 100644
--- a/MoonParser/moon_ast.cpp
+++ b/src/MoonP/moon_ast.cpp
@@ -1,4 +1,12 @@
1#include "moon_ast.h" 1/* Copyright (c) 2020 Jin Li, http://www.luvfight.me
2
3Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
5The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
7THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
8
9#include "MoonP/moon_ast.h"
2 10
3namespace MoonP { 11namespace MoonP {
4 12
diff --git a/MoonParser/moon_ast.h b/src/MoonP/moon_ast.h
index a77fb40..a614465 100644
--- a/MoonParser/moon_ast.h
+++ b/src/MoonP/moon_ast.h
@@ -1,6 +1,14 @@
1/* Copyright (c) 2020 Jin Li, http://www.luvfight.me
2
3Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
5The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
7THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
8
1#pragma once 9#pragma once
2 10
3#include "moon_parser.h" 11#include "MoonP/moon_parser.h"
4 12
5namespace MoonP { 13namespace MoonP {
6 14
@@ -11,7 +19,6 @@ class type##_t : public ast_node \
11public: \ 19public: \
12 virtual int get_type() override { return ast_type<type##_t>(); } \ 20 virtual int get_type() override { return ast_type<type##_t>(); } \
13 virtual size_t getId() const override { return id; } \ 21 virtual size_t getId() const override { return id; } \
14 virtual const char* getName() const override { return #type; }
15 22
16#define AST_NODE(type, id) \ 23#define AST_NODE(type, id) \
17extern rule type; \ 24extern rule type; \
@@ -20,7 +27,6 @@ class type##_t : public ast_container \
20public: \ 27public: \
21 virtual int get_type() override { return ast_type<type##_t>(); } \ 28 virtual int get_type() override { return ast_type<type##_t>(); } \
22 virtual size_t getId() const override { return id; } \ 29 virtual size_t getId() const override { return id; } \
23 virtual const char* getName() const override { return #type; }
24 30
25#define AST_MEMBER(type, ...) \ 31#define AST_MEMBER(type, ...) \
26 type##_t() { \ 32 type##_t() { \
diff --git a/MoonParser/moon_compiler.cpp b/src/MoonP/moon_compiler.cpp
index 85b19ff..f9a86a6 100644
--- a/MoonParser/moon_compiler.cpp
+++ b/src/MoonP/moon_compiler.cpp
@@ -1,3 +1,11 @@
1/* Copyright (c) 2020 Jin Li, http://www.luvfight.me
2
3Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
5The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
7THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
8
1#include <string> 9#include <string>
2#include <unordered_set> 10#include <unordered_set>
3#include <unordered_map> 11#include <unordered_map>
@@ -8,9 +16,9 @@
8#include <sstream> 16#include <sstream>
9#include <string_view> 17#include <string_view>
10using namespace std::string_view_literals; 18using namespace std::string_view_literals;
11#include "parser.hpp" 19#include "MoonP/parser.hpp"
12#include "moon_ast.h" 20#include "MoonP/moon_ast.h"
13#include "moon_compiler.h" 21#include "MoonP/moon_compiler.h"
14 22
15namespace MoonP { 23namespace MoonP {
16 24
@@ -24,12 +32,19 @@ inline std::string s(std::string_view sv) {
24 return std::string(sv); 32 return std::string(sv);
25} 33}
26 34
35const char* moonScriptVersion() {
36 return "0.5.0";
37}
38
27class MoonCompliler { 39class MoonCompliler {
28public: 40public:
29 std::pair<std::string,std::string> complile(const std::string& codes, bool lintGlobalVar, bool implicitReturnRoot, bool lineNumber) { 41 std::pair<std::string,std::string> complile(const std::string& codes, const MoonConfig& config) {
30 _lintGlobalVar = lintGlobalVar; 42 _config = config;
31 _lineNumber = lineNumber; 43 try {
32 _input = _converter.from_bytes(codes); 44 _input = _converter.from_bytes(codes);
45 } catch (const std::range_error&) {
46 return {Empty, "Invalid text encoding."};
47 }
33 error_list el; 48 error_list el;
34 State st; 49 State st;
35 ast_ptr<false, File_t> root; 50 ast_ptr<false, File_t> root;
@@ -43,7 +58,7 @@ public:
43 try { 58 try {
44 str_list out; 59 str_list out;
45 pushScope(); 60 pushScope();
46 transformBlock(root->block, out, implicitReturnRoot); 61 transformBlock(root->block, out, config.implicitReturnRoot);
47 popScope(); 62 popScope();
48 return {std::move(out.back()), Empty}; 63 return {std::move(out.back()), Empty};
49 } catch (const std::logic_error& error) { 64 } catch (const std::logic_error& error) {
@@ -82,8 +97,7 @@ public:
82 _input.clear(); 97 _input.clear();
83 } 98 }
84private: 99private:
85 bool _lintGlobalVar = false; 100 MoonConfig _config;
86 bool _lineNumber = false;
87 int _indentOffset = 0; 101 int _indentOffset = 0;
88 Converter _converter; 102 Converter _converter;
89 input _input; 103 input _input;
@@ -143,12 +157,6 @@ private:
143 Closure 157 Closure
144 }; 158 };
145 159
146 enum class IfUsage {
147 Return,
148 Closure,
149 Common
150 };
151
152 void pushScope() { 160 void pushScope() {
153 _scopes.emplace_back(); 161 _scopes.emplace_back();
154 _scopes.back().vars = std::make_unique<std::unordered_set<std::string>>(); 162 _scopes.back().vars = std::make_unique<std::unordered_set<std::string>>();
@@ -256,7 +264,7 @@ private:
256 } 264 }
257 265
258 const std::string nll(ast_node* node) { 266 const std::string nll(ast_node* node) {
259 if (_lineNumber) { 267 if (_config.reserveLineNumber) {
260 return s(" -- "sv) + std::to_string(node->m_begin.m_line) + _newLine; 268 return s(" -- "sv) + std::to_string(node->m_begin.m_line) + _newLine;
261 } else { 269 } else {
262 return _newLine; 270 return _newLine;
@@ -264,7 +272,7 @@ private:
264 } 272 }
265 273
266 const std::string nlr(ast_node* node) { 274 const std::string nlr(ast_node* node) {
267 if (_lineNumber) { 275 if (_config.reserveLineNumber) {
268 return s(" -- "sv) + std::to_string(node->m_end.m_line) + _newLine; 276 return s(" -- "sv) + std::to_string(node->m_end.m_line) + _newLine;
269 } else { 277 } else {
270 return _newLine; 278 return _newLine;
@@ -280,11 +288,11 @@ private:
280 } 288 }
281 289
282 std::string indent() { 290 std::string indent() {
283 return std::string((_scopes.size() - 1 + _indentOffset) * 2, ' '); 291 return _config.spaceOverTab ? std::string((_scopes.size() - 1 + _indentOffset) * 2, ' ') : std::string(_scopes.size() - 1 + _indentOffset, '\t');
284 } 292 }
285 293
286 std::string indent(int offset) { 294 std::string indent(int offset) {
287 return std::string((_scopes.size() - 1 + _indentOffset + offset) * 2, ' '); 295 return _config.spaceOverTab ? std::string((_scopes.size() - 1 + _indentOffset + offset) * 2, ' ') : std::string(_scopes.size() - 1 + _indentOffset + offset, '\t');
288 } 296 }
289 297
290 std::string clearBuf() { 298 std::string clearBuf() {
@@ -699,12 +707,16 @@ private:
699 } 707 }
700 } 708 }
701 } 709 }
702 auto assign = x->new_ptr<Assign_t>(); 710 if (_config.allowExprNotInTheEndOfBody) {
703 assign->values.dup(expList->exprs); 711 auto assign = x->new_ptr<Assign_t>();
704 auto assignment = x->new_ptr<ExpListAssign_t>(); 712 assign->values.dup(expList->exprs);
705 assignment->expList.set(toAst<ExpList_t>("_", ExpList, x)); 713 auto assignment = x->new_ptr<ExpListAssign_t>();
706 assignment->action.set(assign); 714 assignment->expList.set(toAst<ExpList_t>("_", ExpList, x));
707 transformAssignment(assignment, out); 715 assignment->action.set(assign);
716 transformAssignment(assignment, out);
717 } else {
718 throw std::logic_error(debugInfo("Expression list must appear at the end of body block."sv, expList));
719 }
708 } 720 }
709 break; 721 break;
710 } 722 }
@@ -1051,7 +1063,7 @@ private:
1051 void transformAssignItem(ast_node* value, str_list& out) { 1063 void transformAssignItem(ast_node* value, str_list& out) {
1052 switch (value->getId()) { 1064 switch (value->getId()) {
1053 case "With"_id: transformWithClosure(static_cast<With_t*>(value), out); break; 1065 case "With"_id: transformWithClosure(static_cast<With_t*>(value), out); break;
1054 case "If"_id: transformIf(static_cast<If_t*>(value), out, IfUsage::Closure); break; 1066 case "If"_id: transformIf(static_cast<If_t*>(value), out, ExpUsage::Closure); break;
1055 case "Switch"_id: transformSwitchClosure(static_cast<Switch_t*>(value), out); break; 1067 case "Switch"_id: transformSwitchClosure(static_cast<Switch_t*>(value), out); break;
1056 case "TableBlock"_id: transformTableBlock(static_cast<TableBlock_t*>(value), out); break; 1068 case "TableBlock"_id: transformTableBlock(static_cast<TableBlock_t*>(value), out); break;
1057 case "Exp"_id: transformExp(static_cast<Exp_t*>(value), out); break; 1069 case "Exp"_id: transformExp(static_cast<Exp_t*>(value), out); break;
@@ -1093,8 +1105,8 @@ private:
1093 s("["sv) + std::to_string(index) + s("]"sv) + p.structure}); 1105 s("["sv) + std::to_string(index) + s("]"sv) + p.structure});
1094 } 1106 }
1095 } else { 1107 } else {
1096 bool checkGlobal = _lintGlobalVar; 1108 bool lintGlobal = _config.lintGlobalVariable;
1097 _lintGlobalVar = false; 1109 _config.lintGlobalVariable = false;
1098 auto exp = static_cast<Exp_t*>(pair); 1110 auto exp = static_cast<Exp_t*>(pair);
1099 auto varName = singleVariableFrom(exp); 1111 auto varName = singleVariableFrom(exp);
1100 bool isVariable = !varName.empty(); 1112 bool isVariable = !varName.empty();
@@ -1103,7 +1115,7 @@ private:
1103 transformExp(exp, temp); 1115 transformExp(exp, temp);
1104 varName = std::move(temp.back()); 1116 varName = std::move(temp.back());
1105 } 1117 }
1106 _lintGlobalVar = checkGlobal; 1118 _config.lintGlobalVariable = lintGlobal;
1107 pairs.push_back({ 1119 pairs.push_back({
1108 isVariable, 1120 isVariable,
1109 varName, 1121 varName,
@@ -1133,8 +1145,8 @@ private:
1133 s("."sv) + toString(key) + p.structure}); 1145 s("."sv) + toString(key) + p.structure});
1134 } 1146 }
1135 } else { 1147 } else {
1136 bool checkGlobal = _lintGlobalVar; 1148 bool lintGlobal = _config.lintGlobalVariable;
1137 _lintGlobalVar = false; 1149 _config.lintGlobalVariable = false;
1138 auto varName = singleVariableFrom(exp); 1150 auto varName = singleVariableFrom(exp);
1139 bool isVariable = !varName.empty(); 1151 bool isVariable = !varName.empty();
1140 if (!isVariable) { 1152 if (!isVariable) {
@@ -1142,7 +1154,7 @@ private:
1142 transformExp(exp, temp); 1154 transformExp(exp, temp);
1143 varName = std::move(temp.back()); 1155 varName = std::move(temp.back());
1144 } 1156 }
1145 _lintGlobalVar = checkGlobal; 1157 _config.lintGlobalVariable = lintGlobal;
1146 pairs.push_back({ 1158 pairs.push_back({
1147 isVariable, 1159 isVariable,
1148 varName, 1160 varName,
@@ -1322,7 +1334,7 @@ private:
1322 } 1334 }
1323 } 1335 }
1324 1336
1325 void transformCond(const node_container& nodes, str_list& out, IfUsage usage = IfUsage::Common, bool unless = false) { 1337 void transformCond(const node_container& nodes, str_list& out, ExpUsage usage = ExpUsage::Common, bool unless = false) {
1326 std::vector<ast_ptr<false, ast_node>> ns(false); 1338 std::vector<ast_ptr<false, ast_node>> ns(false);
1327 for (auto it = nodes.rbegin(); it != nodes.rend(); ++it) { 1339 for (auto it = nodes.rbegin(); it != nodes.rend(); ++it) {
1328 ns.push_back(*it); 1340 ns.push_back(*it);
@@ -1362,7 +1374,7 @@ private:
1362 return; 1374 return;
1363 } 1375 }
1364 str_list temp; 1376 str_list temp;
1365 if (usage == IfUsage::Closure) { 1377 if (usage == ExpUsage::Closure) {
1366 temp.push_back(s("(function()"sv) + nll(nodes.front())); 1378 temp.push_back(s("(function()"sv) + nll(nodes.front()));
1367 pushScope(); 1379 pushScope();
1368 } 1380 }
@@ -1389,7 +1401,7 @@ private:
1389 auto var = singleVariableFrom(exp); 1401 auto var = singleVariableFrom(exp);
1390 if (var.empty()) { 1402 if (var.empty()) {
1391 storingValue = true; 1403 storingValue = true;
1392 std::string desVar = getUnusedName("_des_"); 1404 auto desVar = getUnusedName("_des_");
1393 if (assign->values.objects().size() == 1) { 1405 if (assign->values.objects().size() == 1) {
1394 auto var = singleVariableFrom(assign->values.objects().front()); 1406 auto var = singleVariableFrom(assign->values.objects().front());
1395 if (!var.empty()) { 1407 if (!var.empty()) {
@@ -1398,7 +1410,7 @@ private:
1398 } 1410 }
1399 } 1411 }
1400 if (storingValue) { 1412 if (storingValue) {
1401 if (usage != IfUsage::Closure) { 1413 if (usage != ExpUsage::Closure) {
1402 temp.push_back(indent() + s("do"sv) + nll(assign)); 1414 temp.push_back(indent() + s("do"sv) + nll(assign));
1403 pushScope(); 1415 pushScope();
1404 } 1416 }
@@ -1423,7 +1435,7 @@ private:
1423 } else { 1435 } else {
1424 if (!isDefined(var)) { 1436 if (!isDefined(var)) {
1425 storingValue = true; 1437 storingValue = true;
1426 if (usage != IfUsage::Closure) { 1438 if (usage != ExpUsage::Closure) {
1427 temp.push_back(indent() + s("do"sv) + nll(assign)); 1439 temp.push_back(indent() + s("do"sv) + nll(assign));
1428 pushScope(); 1440 pushScope();
1429 } 1441 }
@@ -1467,7 +1479,7 @@ private:
1467 if (pair == ifCondPairs.front() && extraAssignment) { 1479 if (pair == ifCondPairs.front() && extraAssignment) {
1468 transformAssignment(extraAssignment, temp); 1480 transformAssignment(extraAssignment, temp);
1469 } 1481 }
1470 transformBody(pair.second, temp, usage != IfUsage::Common); 1482 transformBody(pair.second, temp, usage != ExpUsage::Common);
1471 popScope(); 1483 popScope();
1472 } 1484 }
1473 if (!pair.first) { 1485 if (!pair.first) {
@@ -1475,22 +1487,22 @@ private:
1475 break; 1487 break;
1476 } 1488 }
1477 } 1489 }
1478 if (storingValue && usage != IfUsage::Closure) { 1490 if (storingValue && usage != ExpUsage::Closure) {
1479 popScope(); 1491 popScope();
1480 temp.push_back(indent() + s("end"sv) + nlr(nodes.front())); 1492 temp.push_back(indent() + s("end"sv) + nlr(nodes.front()));
1481 } 1493 }
1482 if (usage == IfUsage::Closure) { 1494 if (usage == ExpUsage::Closure) {
1483 popScope(); 1495 popScope();
1484 temp.push_back(indent() + s("end)()"sv)); 1496 temp.push_back(indent() + s("end)()"sv));
1485 } 1497 }
1486 out.push_back(join(temp)); 1498 out.push_back(join(temp));
1487 } 1499 }
1488 1500
1489 void transformIf(If_t* ifNode, str_list& out, IfUsage usage = IfUsage::Common) { 1501 void transformIf(If_t* ifNode, str_list& out, ExpUsage usage = ExpUsage::Common) {
1490 transformCond(ifNode->nodes.objects(), out, usage); 1502 transformCond(ifNode->nodes.objects(), out, usage);
1491 } 1503 }
1492 1504
1493 void transformUnless(Unless_t* unless, str_list& out, IfUsage usage = IfUsage::Common) { 1505 void transformUnless(Unless_t* unless, str_list& out, ExpUsage usage = ExpUsage::Common) {
1494 transformCond(unless->nodes.objects(), out, usage, true); 1506 transformCond(unless->nodes.objects(), out, usage, true);
1495 } 1507 }
1496 1508
@@ -1545,7 +1557,7 @@ private:
1545 switch (item->getId()) { 1557 switch (item->getId()) {
1546 case "Variable"_id: { 1558 case "Variable"_id: {
1547 transformVariable(static_cast<Variable_t*>(item), out); 1559 transformVariable(static_cast<Variable_t*>(item), out);
1548 if (_lintGlobalVar && !isDefined(out.back())) { 1560 if (_config.lintGlobalVariable && !isDefined(out.back())) {
1549 if (_globals.find(out.back()) == _globals.end()) { 1561 if (_globals.find(out.back()) == _globals.end()) {
1550 _globals[out.back()] = {item->m_begin.m_line, item->m_begin.m_col}; 1562 _globals[out.back()] = {item->m_begin.m_line, item->m_begin.m_col};
1551 } 1563 }
@@ -1553,7 +1565,7 @@ private:
1553 break; 1565 break;
1554 } 1566 }
1555 case "SelfName"_id: { transformSelfName(static_cast<SelfName_t*>(item), out, invoke); 1567 case "SelfName"_id: { transformSelfName(static_cast<SelfName_t*>(item), out, invoke);
1556 if (_lintGlobalVar) { 1568 if (_config.lintGlobalVariable) {
1557 std::string self("self"sv); 1569 std::string self("self"sv);
1558 if (!isDefined(self)) { 1570 if (!isDefined(self)) {
1559 if (_globals.find(self) == _globals.end()) { 1571 if (_globals.find(self) == _globals.end()) {
@@ -1579,8 +1591,8 @@ private:
1579 auto value = simpleValue->value.get(); 1591 auto value = simpleValue->value.get();
1580 switch (value->getId()) { 1592 switch (value->getId()) {
1581 case "const_value"_id: transform_const_value(static_cast<const_value_t*>(value), out); break; 1593 case "const_value"_id: transform_const_value(static_cast<const_value_t*>(value), out); break;
1582 case "If"_id: transformIf(static_cast<If_t*>(value), out, IfUsage::Closure); break; 1594 case "If"_id: transformIf(static_cast<If_t*>(value), out, ExpUsage::Closure); break;
1583 case "Unless"_id: transformUnless(static_cast<Unless_t*>(value), out, IfUsage::Closure); break; 1595 case "Unless"_id: transformUnless(static_cast<Unless_t*>(value), out, ExpUsage::Closure); break;
1584 case "Switch"_id: transformSwitchClosure(static_cast<Switch_t*>(value), out); break; 1596 case "Switch"_id: transformSwitchClosure(static_cast<Switch_t*>(value), out); break;
1585 case "With"_id: transformWithClosure(static_cast<With_t*>(value), out); break; 1597 case "With"_id: transformWithClosure(static_cast<With_t*>(value), out); break;
1586 case "ClassDecl"_id: transformClassDeclClosure(static_cast<ClassDecl_t*>(value), out); break; 1598 case "ClassDecl"_id: transformClassDeclClosure(static_cast<ClassDecl_t*>(value), out); break;
@@ -1790,10 +1802,10 @@ private:
1790 transformForEachInPlace(static_cast<ForEach_t*>(value), out); 1802 transformForEachInPlace(static_cast<ForEach_t*>(value), out);
1791 return; 1803 return;
1792 case "If"_id: 1804 case "If"_id:
1793 transformIf(static_cast<If_t*>(value), out, IfUsage::Return); 1805 transformIf(static_cast<If_t*>(value), out, ExpUsage::Return);
1794 return; 1806 return;
1795 case "Unless"_id: 1807 case "Unless"_id:
1796 transformUnless(static_cast<Unless_t*>(value), out, IfUsage::Return); 1808 transformUnless(static_cast<Unless_t*>(value), out, ExpUsage::Return);
1797 return; 1809 return;
1798 } 1810 }
1799 } 1811 }
@@ -2075,7 +2087,7 @@ private:
2075 throw std::logic_error(debugInfo("Colon chain item must be followed by invoke arguments."sv, colonItem)); 2087 throw std::logic_error(debugInfo("Colon chain item must be followed by invoke arguments."sv, colonItem));
2076 } 2088 }
2077 if (colonItem->name.is<LuaKeyword_t>()) { 2089 if (colonItem->name.is<LuaKeyword_t>()) {
2078 auto callVar = getUnusedName(s("_call_"sv)); 2090 std::string callVar;
2079 auto block = x->new_ptr<Block_t>(); 2091 auto block = x->new_ptr<Block_t>();
2080 { 2092 {
2081 auto chainValue = x->new_ptr<ChainValue_t>(); 2093 auto chainValue = x->new_ptr<ChainValue_t>();
@@ -2092,14 +2104,18 @@ private:
2092 value->item.set(chainValue); 2104 value->item.set(chainValue);
2093 auto exp = x->new_ptr<Exp_t>(); 2105 auto exp = x->new_ptr<Exp_t>();
2094 exp->value.set(value); 2106 exp->value.set(value);
2095 auto assignment = x->new_ptr<ExpListAssign_t>(); 2107 callVar = singleVariableFrom(exp);
2096 assignment->expList.set(toAst<ExpList_t>(callVar, ExpList, x)); 2108 if (callVar.empty()) {
2097 auto assign = x->new_ptr<Assign_t>(); 2109 callVar = getUnusedName(s("_call_"sv));
2098 assign->values.push_back(exp); 2110 auto assignment = x->new_ptr<ExpListAssign_t>();
2099 assignment->action.set(assign); 2111 assignment->expList.set(toAst<ExpList_t>(callVar, ExpList, x));
2100 auto stmt = x->new_ptr<Statement_t>(); 2112 auto assign = x->new_ptr<Assign_t>();
2101 stmt->content.set(assignment); 2113 assign->values.push_back(exp);
2102 block->statements.push_back(stmt); 2114 assignment->action.set(assign);
2115 auto stmt = x->new_ptr<Statement_t>();
2116 stmt->content.set(assignment);
2117 block->statements.push_back(stmt);
2118 }
2103 } 2119 }
2104 { 2120 {
2105 auto name = toString(colonItem->name); 2121 auto name = toString(colonItem->name);
@@ -2226,7 +2242,7 @@ private:
2226 out.push_back(s(colonChainItem->switchToDot ? "."sv : ":"sv) + name); 2242 out.push_back(s(colonChainItem->switchToDot ? "."sv : ":"sv) + name);
2227 } 2243 }
2228 2244
2229 void transformSlice(Slice_t* slice, str_list& out) { 2245 void transformSlice(Slice_t* slice, str_list&) {
2230 throw std::logic_error(debugInfo("Slice syntax not supported here."sv, slice)); 2246 throw std::logic_error(debugInfo("Slice syntax not supported here."sv, slice));
2231 } 2247 }
2232 2248
@@ -2408,7 +2424,8 @@ private:
2408 switch (loopTarget->getId()) { 2424 switch (loopTarget->getId()) {
2409 case "star_exp"_id: { 2425 case "star_exp"_id: {
2410 auto star_exp = static_cast<star_exp_t*>(loopTarget); 2426 auto star_exp = static_cast<star_exp_t*>(loopTarget);
2411 auto listVar = singleVariableFrom(star_exp->value); 2427 std::string listVar;
2428 if (_config.reuseVariable) listVar = singleVariableFrom(star_exp->value);
2412 auto indexVar = getUnusedName("_index_"); 2429 auto indexVar = getUnusedName("_index_");
2413 varAfter.push_back(indexVar); 2430 varAfter.push_back(indexVar);
2414 auto value = singleValueFrom(star_exp->value); 2431 auto value = singleValueFrom(star_exp->value);
@@ -3230,7 +3247,7 @@ private:
3230 checkAssignable(with->valueList); 3247 checkAssignable(with->valueList);
3231 auto vars = getAssignVars(with); 3248 auto vars = getAssignVars(with);
3232 if (vars.front().empty()) { 3249 if (vars.front().empty()) {
3233 if (with->assigns->values.objects().size() == 1) { 3250 if (_config.reuseVariable && with->assigns->values.objects().size() == 1) {
3234 auto var = singleVariableFrom(with->assigns->values.objects().front()); 3251 auto var = singleVariableFrom(with->assigns->values.objects().front());
3235 if (!var.empty()) { 3252 if (!var.empty()) {
3236 withVar = var; 3253 withVar = var;
@@ -3277,7 +3294,7 @@ private:
3277 transformAssignment(assignment, temp); 3294 transformAssignment(assignment, temp);
3278 } 3295 }
3279 } else { 3296 } else {
3280 withVar = singleVariableFrom(with->valueList); 3297 if (_config.reuseVariable) withVar = singleVariableFrom(with->valueList);
3281 if (withVar.empty()) { 3298 if (withVar.empty()) {
3282 withVar = getUnusedName("_with_"); 3299 withVar = getUnusedName("_with_");
3283 auto assignment = x->new_ptr<ExpListAssign_t>(); 3300 auto assignment = x->new_ptr<ExpListAssign_t>();
@@ -3833,19 +3850,16 @@ private:
3833 3850
3834const std::string MoonCompliler::Empty; 3851const std::string MoonCompliler::Empty;
3835 3852
3836std::pair<std::string,std::string> moonCompile(const std::string& codes, bool implicitReturnRoot, bool lineNumber) { 3853std::tuple<std::string,std::string,GlobalVars> moonCompile(const std::string& codes, const MoonConfig& config) {
3837 return MoonCompliler{}.complile(codes, false, implicitReturnRoot, lineNumber);
3838}
3839
3840std::pair<std::string,std::string> moonCompile(const std::string& codes, std::list<GlobalVar>& globals, bool implicitReturnRoot, bool lineNumber) {
3841 auto compiler = MoonCompliler{}; 3854 auto compiler = MoonCompliler{};
3842 auto result = compiler.complile(codes, true, implicitReturnRoot, lineNumber); 3855 auto result = compiler.complile(codes, config);
3856 auto globals = std::make_unique<std::list<GlobalVar>>();
3843 for (const auto& var : compiler.getGlobals()) { 3857 for (const auto& var : compiler.getGlobals()) {
3844 int line,col; 3858 int line,col;
3845 std::tie(line,col) = var.second; 3859 std::tie(line,col) = var.second;
3846 globals.push_back({var.first, line, col}); 3860 globals->push_back({var.first, line, col});
3847 } 3861 }
3848 return result; 3862 return std::make_tuple(std::move(result.first),std::move(result.second),std::move(globals));
3849} 3863}
3850 3864
3851} // namespace MoonP 3865} // namespace MoonP
diff --git a/src/MoonP/moon_compiler.h b/src/MoonP/moon_compiler.h
new file mode 100644
index 0000000..cb1990c
--- /dev/null
+++ b/src/MoonP/moon_compiler.h
@@ -0,0 +1,39 @@
1/* Copyright (c) 2020 Jin Li, http://www.luvfight.me
2
3Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
5The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
7THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
8
9#pragma once
10
11#include <string>
12#include <tuple>
13#include <list>
14#include <memory>
15
16namespace MoonP {
17
18const char* moonScriptVersion();
19
20struct MoonConfig {
21 bool lintGlobalVariable = false;
22 bool implicitReturnRoot = true;
23 bool reserveLineNumber = false;
24 bool spaceOverTab = false;
25 bool reuseVariable = false;
26 bool allowExprNotInTheEndOfBody = false;
27};
28
29struct GlobalVar {
30 std::string name;
31 int line;
32 int col;
33};
34
35using GlobalVars = std::unique_ptr<std::list<GlobalVar>>;
36
37std::tuple<std::string,std::string,GlobalVars> moonCompile(const std::string& codes, const MoonConfig& config = {});
38
39} // namespace MoonP
diff --git a/MoonParser/moon_parser.cpp b/src/MoonP/moon_parser.cpp
index 2b93c22..7b5183e 100644
--- a/MoonParser/moon_parser.cpp
+++ b/src/MoonP/moon_parser.cpp
@@ -1,4 +1,14 @@
1#include "moon_parser.h" 1/* Copyright (c) 2020 Jin Li, http://www.luvfight.me
2
3Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
5The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
7THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
8
9#include "MoonP/moon_parser.h"
10
11namespace pl = parserlib;
2 12
3namespace MoonP { 13namespace MoonP {
4 14
@@ -35,15 +45,18 @@ rule EmptyLine = SpaceBreak;
35rule AlphaNum = range('a', 'z') | range('A', 'Z') | range('0', '9') | '_'; 45rule AlphaNum = range('a', 'z') | range('A', 'Z') | range('0', '9') | '_';
36rule Name = (range('a', 'z') | range('A', 'Z') | '_') >> *AlphaNum; 46rule Name = (range('a', 'z') | range('A', 'Z') | '_') >> *AlphaNum;
37rule Num = 47rule Num =
48(
49 "0x" >>
50 +(range('0', '9') | range('a', 'f') | range('A', 'F')) >>
51 -(-set("uU") >> set("lL") >> set("lL"))
52) | (
53 +range('0', '9') >> -set("uU") >> set("lL") >> set("lL")
54) | (
38 ( 55 (
39 "0x" >> 56 (+range('0', '9') >> -('.' >> +range('0', '9'))) |
40 +(range('0', '9') | range('a', 'f') | range('A', 'F')) 57 ('.' >> +range('0', '9'))
41 ) | ( 58 ) >> -(set("eE") >> -expr('-') >> +range('0', '9'))
42 ( 59);
43 (+range('0', '9') >> -('.' >> +range('0', '9'))) |
44 ('.' >> +range('0', '9'))
45 ) >> -(set("eE") >> -expr('-') >> +range('0', '9'))
46 );
47rule Cut = false_(); 60rule Cut = false_();
48rule Seperator = true_(); 61rule Seperator = true_();
49 62
@@ -52,7 +65,7 @@ rule Seperator = true_();
52#define ensure(patt, finally) (((patt) >> (finally)) | ((finally) >> (Cut))) 65#define ensure(patt, finally) (((patt) >> (finally)) | ((finally) >> (Cut)))
53#define key(str) (Space >> str >> not_(AlphaNum)) 66#define key(str) (Space >> str >> not_(AlphaNum))
54 67
55rule Variable = user(Name, [](const item_t& item) { 68rule Variable = pl::user(Name, [](const item_t& item) {
56 State* st = reinterpret_cast<State*>(item.user_data); 69 State* st = reinterpret_cast<State*>(item.user_data);
57 for (auto it = item.begin; it != item.end; ++it) st->buffer += static_cast<char>(*it); 70 for (auto it = item.begin; it != item.end; ++it) st->buffer += static_cast<char>(*it);
58 auto it = State::keywords.find(st->buffer); 71 auto it = State::keywords.find(st->buffer);
@@ -60,7 +73,7 @@ rule Variable = user(Name, [](const item_t& item) {
60 return it == State::keywords.end(); 73 return it == State::keywords.end();
61}); 74});
62 75
63rule LuaKeyword = user(Name, [](const item_t& item) { 76rule LuaKeyword = pl::user(Name, [](const item_t& item) {
64 State* st = reinterpret_cast<State*>(item.user_data); 77 State* st = reinterpret_cast<State*>(item.user_data);
65 for (auto it = item.begin; it != item.end; ++it) st->buffer += static_cast<char>(*it); 78 for (auto it = item.begin; it != item.end; ++it) st->buffer += static_cast<char>(*it);
66 auto it = State::luaKeywords.find(st->buffer); 79 auto it = State::luaKeywords.find(st->buffer);
@@ -77,7 +90,7 @@ rule SelfName = Space >> (self_class_name | self_class | self_name | self);
77rule KeyName = SelfName | Space >> Name; 90rule KeyName = SelfName | Space >> Name;
78rule VarArg = Space >> "..."; 91rule VarArg = Space >> "...";
79 92
80rule check_indent = user(Indent, [](const item_t& item) { 93rule check_indent = pl::user(Indent, [](const item_t& item) {
81 int indent = 0; 94 int indent = 0;
82 for (input_it i = item.begin; i != item.end; ++i) { 95 for (input_it i = item.begin; i != item.end; ++i) {
83 switch (*i) { 96 switch (*i) {
@@ -90,7 +103,7 @@ rule check_indent = user(Indent, [](const item_t& item) {
90}); 103});
91rule CheckIndent = and_(check_indent); 104rule CheckIndent = and_(check_indent);
92 105
93rule advance = user(Indent, [](const item_t& item) { 106rule advance = pl::user(Indent, [](const item_t& item) {
94 int indent = 0; 107 int indent = 0;
95 for (input_it i = item.begin; i != item.end; ++i) { 108 for (input_it i = item.begin; i != item.end; ++i) {
96 switch (*i) { 109 switch (*i) {
@@ -108,7 +121,7 @@ rule advance = user(Indent, [](const item_t& item) {
108}); 121});
109rule Advance = and_(advance); 122rule Advance = and_(advance);
110 123
111rule push_indent = user(Indent, [](const item_t& item) { 124rule push_indent = pl::user(Indent, [](const item_t& item) {
112 int indent = 0; 125 int indent = 0;
113 for (input_it i = item.begin; i != item.end; ++i) { 126 for (input_it i = item.begin; i != item.end; ++i) {
114 switch (*i) { 127 switch (*i) {
@@ -122,13 +135,13 @@ rule push_indent = user(Indent, [](const item_t& item) {
122}); 135});
123rule PushIndent = and_(push_indent); 136rule PushIndent = and_(push_indent);
124 137
125rule PreventIndent = user(true_(), [](const item_t& item) { 138rule PreventIndent = pl::user(true_(), [](const item_t& item) {
126 State* st = reinterpret_cast<State*>(item.user_data); 139 State* st = reinterpret_cast<State*>(item.user_data);
127 st->indents.push(-1); 140 st->indents.push(-1);
128 return true; 141 return true;
129}); 142});
130 143
131rule PopIndent = user(true_(), [](const item_t& item) { 144rule PopIndent = pl::user(true_(), [](const item_t& item) {
132 State* st = reinterpret_cast<State*>(item.user_data); 145 State* st = reinterpret_cast<State*>(item.user_data);
133 st->indents.pop(); 146 st->indents.pop();
134 return true; 147 return true;
@@ -166,8 +179,8 @@ rule SwitchElse = key("else") >> Body;
166rule SwitchBlock = *EmptyLine >> 179rule SwitchBlock = *EmptyLine >>
167 Advance >> Seperator >> 180 Advance >> Seperator >>
168 SwitchCase >> 181 SwitchCase >>
169 *(+Break >> SwitchCase) >> 182 *(+SpaceBreak >> SwitchCase) >>
170 -(+Break >> SwitchElse) >> 183 -(+SpaceBreak >> SwitchElse) >>
171 PopIndent; 184 PopIndent;
172 185
173rule Switch = key("switch") >> 186rule Switch = key("switch") >>
@@ -199,20 +212,20 @@ rule ForEach = key("for") >> AssignableNameList >> key("in") >>
199 DisableDo >> ensure(for_in, PopDo) >> 212 DisableDo >> ensure(for_in, PopDo) >>
200 -key("do") >> Body; 213 -key("do") >> Body;
201 214
202rule Do = user(key("do") >> Body, [](const item_t& item) 215rule Do = pl::user(key("do") >> Body, [](const item_t& item)
203{ 216{
204 State* st = reinterpret_cast<State*>(item.user_data); 217 State* st = reinterpret_cast<State*>(item.user_data);
205 return st->doStack.empty() || st->doStack.top(); 218 return st->doStack.empty() || st->doStack.top();
206}); 219});
207 220
208rule DisableDo = user(true_(), [](const item_t& item) 221rule DisableDo = pl::user(true_(), [](const item_t& item)
209{ 222{
210 State* st = reinterpret_cast<State*>(item.user_data); 223 State* st = reinterpret_cast<State*>(item.user_data);
211 st->doStack.push(false); 224 st->doStack.push(false);
212 return true; 225 return true;
213}); 226});
214 227
215rule PopDo = user(true_(), [](const item_t& item) 228rule PopDo = pl::user(true_(), [](const item_t& item)
216{ 229{
217 State* st = reinterpret_cast<State*>(item.user_data); 230 State* st = reinterpret_cast<State*>(item.user_data);
218 st->doStack.pop(); 231 st->doStack.pop();
@@ -299,7 +312,7 @@ rule String = Space >> (DoubleString | SingleString | LuaString);
299rule lua_string_open = '[' >> *expr('=') >> '['; 312rule lua_string_open = '[' >> *expr('=') >> '[';
300rule lua_string_close = ']' >> *expr('=') >> ']'; 313rule lua_string_close = ']' >> *expr('=') >> ']';
301 314
302rule LuaStringOpen = user(lua_string_open, [](const item_t& item) 315rule LuaStringOpen = pl::user(lua_string_open, [](const item_t& item)
303{ 316{
304 size_t count = std::distance(item.begin, item.end); 317 size_t count = std::distance(item.begin, item.end);
305 State* st = reinterpret_cast<State*>(item.user_data); 318 State* st = reinterpret_cast<State*>(item.user_data);
@@ -307,7 +320,7 @@ rule LuaStringOpen = user(lua_string_open, [](const item_t& item)
307 return true; 320 return true;
308}); 321});
309 322
310rule LuaStringClose = user(lua_string_close, [](const item_t& item) 323rule LuaStringClose = pl::user(lua_string_close, [](const item_t& item)
311{ 324{
312 size_t count = std::distance(item.begin, item.end); 325 size_t count = std::distance(item.begin, item.end);
313 State* st = reinterpret_cast<State*>(item.user_data); 326 State* st = reinterpret_cast<State*>(item.user_data);
@@ -316,7 +329,7 @@ rule LuaStringClose = user(lua_string_close, [](const item_t& item)
316 329
317rule LuaStringContent = *(not_(LuaStringClose) >> (Break | Any)); 330rule LuaStringContent = *(not_(LuaStringClose) >> (Break | Any));
318 331
319rule LuaString = user(LuaStringOpen >> -Break >> LuaStringContent >> LuaStringClose, [](const item_t& item) 332rule LuaString = pl::user(LuaStringOpen >> -Break >> LuaStringContent >> LuaStringClose, [](const item_t& item)
320{ 333{
321 State* st = reinterpret_cast<State*>(item.user_data); 334 State* st = reinterpret_cast<State*>(item.user_data);
322 st->stringOpen = -1; 335 st->stringOpen = -1;
diff --git a/src/MoonP/moon_parser.h b/src/MoonP/moon_parser.h
new file mode 100644
index 0000000..fc4ee55
--- /dev/null
+++ b/src/MoonP/moon_parser.h
@@ -0,0 +1,35 @@
1/* Copyright (c) 2020 Jin Li, http://www.luvfight.me
2
3Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
5The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
7THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
8
9#pragma once
10
11#include <string>
12#include <codecvt>
13#include <unordered_set>
14#include <stack>
15#include <algorithm>
16#include <vector>
17#include "MoonP/ast.hpp"
18using namespace parserlib;
19
20namespace MoonP {
21
22struct State {
23 State() {
24 indents.push(0);
25 stringOpen = -1;
26 }
27 std::string buffer;
28 size_t stringOpen;
29 std::stack<int> indents;
30 std::stack<bool> doStack;
31 static std::unordered_set<std::string> luaKeywords;
32 static std::unordered_set<std::string> keywords;
33};
34
35} // namespace MoonP
diff --git a/MoonParser/parser.cpp b/src/MoonP/parser.cpp
index 03857c6..19c0068 100644
--- a/MoonParser/parser.cpp
+++ b/src/MoonP/parser.cpp
@@ -1,3 +1,13 @@
1/* Copyright (c) 2012, Achilleas Margaritis, modified by Jin Li
2All rights reserved.
3
4 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
5
6 Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
7 Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
8
9THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
10
1#include <cstdlib> 11#include <cstdlib>
2#include <cstring> 12#include <cstring>
3#include <cassert> 13#include <cassert>
@@ -5,7 +15,7 @@
5#include <unordered_map> 15#include <unordered_map>
6#include <unordered_set> 16#include <unordered_set>
7 17
8#include "parser.hpp" 18#include "MoonP/parser.hpp"
9 19
10 20
11namespace parserlib { 21namespace parserlib {
@@ -768,12 +778,12 @@ public:
768class _true : public _expr { 778class _true : public _expr {
769public: 779public:
770 //parse with whitespace 780 //parse with whitespace
771 virtual bool parse_non_term(_context &con) const { 781 virtual bool parse_non_term(_context &) const {
772 return true; 782 return true;
773 } 783 }
774 784
775 //parse terminal 785 //parse terminal
776 virtual bool parse_term(_context &con) const { 786 virtual bool parse_term(_context &) const {
777 return true; 787 return true;
778 } 788 }
779}; 789};
@@ -783,12 +793,12 @@ public:
783class _false: public _expr { 793class _false: public _expr {
784public: 794public:
785 //parse with whitespace 795 //parse with whitespace
786 virtual bool parse_non_term(_context &con) const { 796 virtual bool parse_non_term(_context &) const {
787 return false; 797 return false;
788 } 798 }
789 799
790 //parse terminal 800 //parse terminal
791 virtual bool parse_term(_context &con) const { 801 virtual bool parse_term(_context &) const {
792 return false; 802 return false;
793 } 803 }
794}; 804};
@@ -1208,10 +1218,9 @@ rule::rule(rule &r) :
1208 1218
1209 1219
1210/** invalid constructor from rule (required by gcc). 1220/** invalid constructor from rule (required by gcc).
1211 @param r rule.
1212 @exception std::logic_error always thrown. 1221 @exception std::logic_error always thrown.
1213 */ 1222 */
1214rule::rule(const rule &r) { 1223rule::rule(const rule &) {
1215 throw std::logic_error("invalid operation"); 1224 throw std::logic_error("invalid operation");
1216} 1225}
1217 1226
diff --git a/MoonParser/parser.hpp b/src/MoonP/parser.hpp
index cbf0168..9739465 100644
--- a/MoonParser/parser.hpp
+++ b/src/MoonP/parser.hpp
@@ -1,3 +1,13 @@
1/* Copyright (c) 2012, Achilleas Margaritis, modified by Jin Li
2All rights reserved.
3
4 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
5
6 Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
7 Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
8
9THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
10
1#pragma once 11#pragma once
2 12
3 13
diff --git a/src/moonc.cpp b/src/moonc.cpp
new file mode 100644
index 0000000..d9d3ce3
--- /dev/null
+++ b/src/moonc.cpp
@@ -0,0 +1,178 @@
1/* Copyright (c) 2020 Jin Li, http://www.luvfight.me
2
3Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
5The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
7THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
8#include <iostream>
9#include <iomanip>
10#include <fstream>
11#include <chrono>
12#include "MoonP/moon_compiler.h"
13#include "MoonP/parser.hpp"
14#include "MoonP/moon_ast.h"
15
16int main(int narg, const char** args) {
17 const char* help =
18"Usage: moonc [options|files] ...\n\n"
19" -h Print this message\n"
20" -t path Specify where to place compiled files\n"
21" -o file Write output to file\n"
22" -p Write output to standard out\n"
23" -b Dump compile time (doesn't write output)\n"
24" -l Write line numbers from source codes\n"
25" -a Allow expression list not in the end of body block\n"
26" -s Use space over tab\n"
27" -v Print version\n";
28 if (narg == 0) {
29 std::cout << help;
30 return 0;
31 }
32 MoonP::MoonConfig config;
33 bool writeToFile = true;
34 bool dumpCompileTime = false;
35 std::string targetPath;
36 std::string resultFile;
37 std::list<std::string> files;
38 for (int i = 1; i < narg; ++i) {
39 switch (hash(args[i])) {
40 case "-a"_id:
41 config.allowExprNotInTheEndOfBody = true;
42 break;
43 case "-s"_id:
44 config.spaceOverTab = true;
45 break;
46 case "-l"_id:
47 config.reserveLineNumber = true;
48 break;
49 case "-r"_id:
50 config.reuseVariable = true;
51 break;
52 case "-p"_id:
53 writeToFile = false;
54 break;
55 case "-t"_id:
56 ++i;
57 if (i < narg) {
58 targetPath = args[i];
59 } else {
60 std::cout << help;
61 return 1;
62 }
63 break;
64 case "-b"_id:
65 dumpCompileTime = true;
66 break;
67 case "-h"_id:
68 std::cout << help;
69 return 0;
70 case "-v"_id:
71 std::cout << "Moonscript version: " << MoonP::moonScriptVersion() << '\n';
72 break;
73 case "-o"_id:
74 ++i;
75 if (i < narg) {
76 resultFile = args[i];
77 } else {
78 std::cout << help;
79 return 1;
80 }
81 break;
82 default:
83 files.push_back(args[i]);
84 break;
85 }
86 }
87 if (files.empty()) {
88 std::cout << help;
89 return 0;
90 }
91 if (!resultFile.empty() && files.size() > 1) {
92 std::cout << "Error: -o can not be used with multiple input files.\n";
93 std::cout << help;
94 }
95 for (const auto& file : files) {
96 std::ifstream input(file, input.in);
97 if (input) {
98 std::string s(
99 (std::istreambuf_iterator<char>(input)),
100 std::istreambuf_iterator<char>());
101 if (dumpCompileTime) {
102 auto start = std::chrono::high_resolution_clock::now();
103 auto result = MoonP::moonCompile(s, config);
104 auto end = std::chrono::high_resolution_clock::now();
105 if (!std::get<0>(result).empty()) {
106 std::chrono::duration<double> diff = end - start;
107 error_list el;
108 MoonP::State st;
109 start = std::chrono::high_resolution_clock::now();
110 auto input = Converter{}.from_bytes(s);
111 parserlib::parse<MoonP::File_t>(input, MoonP::File, el, &st);
112 end = std::chrono::high_resolution_clock::now();
113 std::chrono::duration<double> parseDiff = end - start;
114 std::cout << file << " \n";
115 std::cout << "Parse time: " << std::setprecision(5) << parseDiff.count() * 1000 << " ms\n";
116 std::cout << "Compile time: " << std::setprecision(5) << (diff.count() - parseDiff.count()) * 1000 << " ms\n\n";
117 } else {
118 std::cout << "Fail to compile: " << file << ".\n";
119 std::cout << std::get<1>(result) << '\n';
120 return 1;
121 }
122 continue;
123 }
124 auto result = MoonP::moonCompile(s, config);
125 if (!std::get<0>(result).empty()) {
126 if (!writeToFile) {
127 std::cout << std::get<0>(result) << '\n';
128 } else {
129 std::string targetFile;
130 if (resultFile.empty()) {
131 std::string ext;
132 targetFile = file;
133 size_t pos = file.rfind('.');
134 if (pos != std::string::npos) {
135 ext = file.substr(pos + 1);
136 for (size_t i = 0; i < ext.length(); i++) {
137 ext[i] = static_cast<char>(tolower(ext[i]));
138 }
139 targetFile = file.substr(0, pos) + ".lua";
140 }
141 if (!targetPath.empty()) {
142 std::string name;
143 pos = targetFile.find_last_of("/\\");
144 if (pos == std::string::npos) {
145 name = targetFile;
146 } else {
147 name = targetFile.substr(pos + 1);
148 }
149 if (targetPath.back() != '/' && targetPath.back() != '\\') {
150 targetPath.append("/");
151 }
152 targetFile = targetPath + name;
153 }
154 } else {
155 targetFile = resultFile;
156 }
157 std::ofstream output(targetFile, output.trunc | output.out);
158 if (output) {
159 const auto& codes = std::get<0>(result);
160 output.write(codes.c_str(), codes.size());
161 std::cout << "Built " << file << '\n';
162 } else {
163 std::cout << "Fail to write file: " << targetFile << ".\n";
164 return 1;
165 }
166 }
167 } else {
168 std::cout << "Fail to compile: " << file << ".\n";
169 std::cout << std::get<1>(result) << '\n';
170 return 1;
171 }
172 } else {
173 std::cout << "Fail to read file: " << file << ".\n";
174 return 1;
175 }
176 }
177 return 0;
178}