summaryrefslogtreecommitdiff
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
parent975167856ed0b11c2ede03c6eb750ca4e4a6a7fc (diff)
downloadyuescript-52a6536103f46c26a3ba9b149b0fe7b40d524d8c.tar.gz
yuescript-52a6536103f46c26a3ba9b149b0fe7b40d524d8c.tar.bz2
yuescript-52a6536103f46c26a3ba9b149b0fe7b40d524d8c.zip
update.
-rw-r--r--MoonParser/moon_compiler.h18
-rw-r--r--MoonParser/moon_parser.h27
-rw-r--r--MoonParser/moonc.cpp21
-rw-r--r--MoonPlus.xcodeproj/project.pbxproj (renamed from MoonParser.xcodeproj/project.pbxproj)110
-rw-r--r--MoonPlus.xcodeproj/project.xcworkspace/contents.xcworkspacedata (renamed from MoonParser.xcodeproj/project.xcworkspace/contents.xcworkspacedata)2
-rw-r--r--MoonPlus.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist (renamed from MoonParser.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist)0
-rw-r--r--makefile236
-rw-r--r--spec/inputs/assign.moon30
-rw-r--r--spec/inputs/bubbling.moon28
-rw-r--r--spec/inputs/class.moon213
-rw-r--r--spec/inputs/comprehension.moon52
-rw-r--r--spec/inputs/cond.moon190
-rw-r--r--spec/inputs/destructure.moon100
-rw-r--r--spec/inputs/do.moon27
-rw-r--r--spec/inputs/export.moon77
-rw-r--r--spec/inputs/funcs.moon158
-rw-r--r--spec/inputs/import.moon48
-rw-r--r--spec/inputs/lists.moon72
-rw-r--r--spec/inputs/literals.moon46
-rw-r--r--spec/inputs/local.moon94
-rw-r--r--spec/inputs/loops.moon133
-rw-r--r--spec/inputs/operators.moon72
-rw-r--r--spec/inputs/plus.moon7
-rw-r--r--spec/inputs/return.moon55
-rw-r--r--spec/inputs/string.moon66
-rw-r--r--spec/inputs/stub.moon16
-rw-r--r--spec/inputs/switch.moon64
-rw-r--r--spec/inputs/syntax.moon272
-rw-r--r--spec/inputs/tables.moon161
-rw-r--r--spec/inputs/unless_else.moon5
-rw-r--r--spec/inputs/using.moon21
-rw-r--r--spec/inputs/whitespace.moon102
-rw-r--r--spec/inputs/with.moon118
-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
44 files changed, 2975 insertions, 258 deletions
diff --git a/MoonParser/moon_compiler.h b/MoonParser/moon_compiler.h
deleted file mode 100644
index e54c774..0000000
--- a/MoonParser/moon_compiler.h
+++ /dev/null
@@ -1,18 +0,0 @@
1#pragma once
2
3#include <string>
4#include <tuple>
5#include <list>
6
7namespace MoonP {
8
9std::pair<std::string,std::string> moonCompile(const std::string& codes, bool implicitReturnRoot = true, bool lineNumber = true);
10
11struct GlobalVar {
12 std::string name;
13 int line;
14 int col;
15};
16std::pair<std::string,std::string> moonCompile(const std::string& codes, std::list<GlobalVar>& globals, bool implicitReturnRoot = true, bool lineNumber = true);
17
18} // namespace MoonP
diff --git a/MoonParser/moon_parser.h b/MoonParser/moon_parser.h
deleted file mode 100644
index 07380cc..0000000
--- a/MoonParser/moon_parser.h
+++ /dev/null
@@ -1,27 +0,0 @@
1#pragma once
2
3#include <string>
4#include <codecvt>
5#include <unordered_set>
6#include <stack>
7#include <algorithm>
8#include <vector>
9#include "ast.hpp"
10using namespace parserlib;
11
12namespace MoonP {
13
14struct State {
15 State() {
16 indents.push(0);
17 stringOpen = -1;
18 }
19 std::string buffer;
20 size_t stringOpen;
21 std::stack<int> indents;
22 std::stack<bool> doStack;
23 static std::unordered_set<std::string> luaKeywords;
24 static std::unordered_set<std::string> keywords;
25};
26
27} // namespace MoonP
diff --git a/MoonParser/moonc.cpp b/MoonParser/moonc.cpp
deleted file mode 100644
index 1a383fe..0000000
--- a/MoonParser/moonc.cpp
+++ /dev/null
@@ -1,21 +0,0 @@
1#include <iostream>
2#include "moon_compiler.h"
3
4int main()
5{
6 std::string s = R"TestCodesHere(
7print nil + 1
8)TestCodesHere";
9 std::list<MoonP::GlobalVar> globals;
10 auto result = MoonP::moonCompile(s, globals, true, false);
11 if (!result.first.empty()) {
12 std::cout << result.first << '\n';
13 } else {
14 std::cout << result.second << '\n';
15 }
16 std::cout << "globals:\n";
17 for (const auto& var : globals) {
18 std::cout << var.name << '\n';
19 }
20 return 0;
21}
diff --git a/MoonParser.xcodeproj/project.pbxproj b/MoonPlus.xcodeproj/project.pbxproj
index c9744d1..99a51bf 100644
--- a/MoonParser.xcodeproj/project.pbxproj
+++ b/MoonPlus.xcodeproj/project.pbxproj
@@ -7,12 +7,12 @@
7 objects = { 7 objects = {
8 8
9/* Begin PBXBuildFile section */ 9/* Begin PBXBuildFile section */
10 3C1C21CD2367E69100147A19 /* moon_compiler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C1C21CC2367E69100147A19 /* moon_compiler.cpp */; }; 10 3C1C21EE2368322900147A19 /* ast.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C1C21E52368322900147A19 /* ast.cpp */; };
11 3C3B1C601F1EF0AB0052A206 /* moon_ast.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C3B1C5E1F1EF0AB0052A206 /* moon_ast.cpp */; }; 11 3C1C21EF2368322900147A19 /* moon_ast.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C1C21E62368322900147A19 /* moon_ast.cpp */; };
12 3C54E26C234C80CC00202423 /* moonc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C54E26B234C80CC00202423 /* moonc.cpp */; }; 12 3C1C21F02368322900147A19 /* moon_compiler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C1C21E92368322900147A19 /* moon_compiler.cpp */; };
13 3C6FFA331F16F97400541BCA /* ast.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C6FFA2D1F16F97400541BCA /* ast.cpp */; }; 13 3C1C21F12368322900147A19 /* parser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C1C21EA2368322900147A19 /* parser.cpp */; };
14 3C6FFA341F16F97400541BCA /* moon_parser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C6FFA2F1F16F97400541BCA /* moon_parser.cpp */; }; 14 3C1C21F22368322900147A19 /* moon_parser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C1C21EB2368322900147A19 /* moon_parser.cpp */; };
15 3C6FFA351F16F97400541BCA /* parser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C6FFA301F16F97400541BCA /* parser.cpp */; }; 15 3C1C21F32368322900147A19 /* moonc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C1C21ED2368322900147A19 /* moonc.cpp */; };
16/* End PBXBuildFile section */ 16/* End PBXBuildFile section */
17 17
18/* Begin PBXCopyFilesBuildPhase section */ 18/* Begin PBXCopyFilesBuildPhase section */
@@ -28,18 +28,18 @@
28/* End PBXCopyFilesBuildPhase section */ 28/* End PBXCopyFilesBuildPhase section */
29 29
30/* Begin PBXFileReference section */ 30/* Begin PBXFileReference section */
31 3C0F0F6C1EF3781E000EADDB /* MoonParser */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = MoonParser; sourceTree = BUILT_PRODUCTS_DIR; }; 31 3C0F0F6C1EF3781E000EADDB /* MoonPlusPlus */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = MoonPlusPlus; sourceTree = BUILT_PRODUCTS_DIR; };
32 3C1C21CB2367E69100147A19 /* moon_compiler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = moon_compiler.h; sourceTree = "<group>"; }; 32 3C1C21E32368322900147A19 /* parser.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = parser.hpp; sourceTree = "<group>"; };
33 3C1C21CC2367E69100147A19 /* moon_compiler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = moon_compiler.cpp; sourceTree = "<group>"; }; 33 3C1C21E42368322900147A19 /* moon_compiler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = moon_compiler.h; sourceTree = "<group>"; };
34 3C3B1C5E1F1EF0AB0052A206 /* moon_ast.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = moon_ast.cpp; sourceTree = "<group>"; }; 34 3C1C21E52368322900147A19 /* ast.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ast.cpp; sourceTree = "<group>"; };
35 3C3B1C5F1F1EF0AB0052A206 /* moon_ast.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = moon_ast.h; sourceTree = "<group>"; }; 35 3C1C21E62368322900147A19 /* moon_ast.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = moon_ast.cpp; sourceTree = "<group>"; };
36 3C3B1C611F1EFC810052A206 /* moon_parser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = moon_parser.h; sourceTree = "<group>"; }; 36 3C1C21E72368322900147A19 /* moon_ast.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = moon_ast.h; sourceTree = "<group>"; };
37 3C54E26B234C80CC00202423 /* moonc.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = moonc.cpp; sourceTree = "<group>"; }; 37 3C1C21E82368322900147A19 /* moon_parser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = moon_parser.h; sourceTree = "<group>"; };
38 3C6FFA2D1F16F97400541BCA /* ast.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ast.cpp; sourceTree = "<group>"; }; 38 3C1C21E92368322900147A19 /* moon_compiler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = moon_compiler.cpp; sourceTree = "<group>"; };
39 3C6FFA2E1F16F97400541BCA /* ast.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = ast.hpp; sourceTree = "<group>"; }; 39 3C1C21EA2368322900147A19 /* parser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = parser.cpp; sourceTree = "<group>"; };
40 3C6FFA2F1F16F97400541BCA /* moon_parser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = moon_parser.cpp; sourceTree = "<group>"; }; 40 3C1C21EB2368322900147A19 /* moon_parser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = moon_parser.cpp; sourceTree = "<group>"; };
41 3C6FFA301F16F97400541BCA /* parser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = parser.cpp; sourceTree = "<group>"; }; 41 3C1C21EC2368322900147A19 /* ast.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = ast.hpp; sourceTree = "<group>"; };
42 3C6FFA311F16F97400541BCA /* parser.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = parser.hpp; sourceTree = "<group>"; }; 42 3C1C21ED2368322900147A19 /* moonc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = moonc.cpp; sourceTree = "<group>"; };
43/* End PBXFileReference section */ 43/* End PBXFileReference section */
44 44
45/* Begin PBXFrameworksBuildPhase section */ 45/* Begin PBXFrameworksBuildPhase section */
@@ -53,46 +53,54 @@
53/* End PBXFrameworksBuildPhase section */ 53/* End PBXFrameworksBuildPhase section */
54 54
55/* Begin PBXGroup section */ 55/* Begin PBXGroup section */
56 3C0631A11F0CBE210089D0AB /* MoonParser */ = { 56 3C0F0F631EF3781E000EADDB = {
57 isa = PBXGroup; 57 isa = PBXGroup;
58 children = ( 58 children = (
59 3C6FFA2D1F16F97400541BCA /* ast.cpp */, 59 3C1C21E12368322900147A19 /* src */,
60 3C6FFA2E1F16F97400541BCA /* ast.hpp */, 60 3C0F0F6D1EF3781E000EADDB /* Products */,
61 3C6FFA301F16F97400541BCA /* parser.cpp */,
62 3C6FFA311F16F97400541BCA /* parser.hpp */,
63 3C6FFA2F1F16F97400541BCA /* moon_parser.cpp */,
64 3C3B1C611F1EFC810052A206 /* moon_parser.h */,
65 3C3B1C5E1F1EF0AB0052A206 /* moon_ast.cpp */,
66 3C3B1C5F1F1EF0AB0052A206 /* moon_ast.h */,
67 3C1C21CC2367E69100147A19 /* moon_compiler.cpp */,
68 3C1C21CB2367E69100147A19 /* moon_compiler.h */,
69 3C54E26B234C80CC00202423 /* moonc.cpp */,
70 ); 61 );
71 path = MoonParser;
72 sourceTree = "<group>"; 62 sourceTree = "<group>";
73 }; 63 };
74 3C0F0F631EF3781E000EADDB = { 64 3C0F0F6D1EF3781E000EADDB /* Products */ = {
75 isa = PBXGroup; 65 isa = PBXGroup;
76 children = ( 66 children = (
77 3C0631A11F0CBE210089D0AB /* MoonParser */, 67 3C0F0F6C1EF3781E000EADDB /* MoonPlusPlus */,
78 3C0F0F6D1EF3781E000EADDB /* Products */,
79 ); 68 );
69 name = Products;
80 sourceTree = "<group>"; 70 sourceTree = "<group>";
81 }; 71 };
82 3C0F0F6D1EF3781E000EADDB /* Products */ = { 72 3C1C21E12368322900147A19 /* src */ = {
83 isa = PBXGroup; 73 isa = PBXGroup;
84 children = ( 74 children = (
85 3C0F0F6C1EF3781E000EADDB /* MoonParser */, 75 3C1C21E22368322900147A19 /* MoonP */,
76 3C1C21ED2368322900147A19 /* moonc.cpp */,
86 ); 77 );
87 name = Products; 78 path = src;
79 sourceTree = "<group>";
80 };
81 3C1C21E22368322900147A19 /* MoonP */ = {
82 isa = PBXGroup;
83 children = (
84 3C1C21E32368322900147A19 /* parser.hpp */,
85 3C1C21E42368322900147A19 /* moon_compiler.h */,
86 3C1C21E52368322900147A19 /* ast.cpp */,
87 3C1C21E62368322900147A19 /* moon_ast.cpp */,
88 3C1C21E72368322900147A19 /* moon_ast.h */,
89 3C1C21E82368322900147A19 /* moon_parser.h */,
90 3C1C21E92368322900147A19 /* moon_compiler.cpp */,
91 3C1C21EA2368322900147A19 /* parser.cpp */,
92 3C1C21EB2368322900147A19 /* moon_parser.cpp */,
93 3C1C21EC2368322900147A19 /* ast.hpp */,
94 );
95 path = MoonP;
88 sourceTree = "<group>"; 96 sourceTree = "<group>";
89 }; 97 };
90/* End PBXGroup section */ 98/* End PBXGroup section */
91 99
92/* Begin PBXNativeTarget section */ 100/* Begin PBXNativeTarget section */
93 3C0F0F6B1EF3781E000EADDB /* MoonParser */ = { 101 3C0F0F6B1EF3781E000EADDB /* MoonPlusPlus */ = {
94 isa = PBXNativeTarget; 102 isa = PBXNativeTarget;
95 buildConfigurationList = 3C0F0F731EF3781E000EADDB /* Build configuration list for PBXNativeTarget "MoonParser" */; 103 buildConfigurationList = 3C0F0F731EF3781E000EADDB /* Build configuration list for PBXNativeTarget "MoonPlusPlus" */;
96 buildPhases = ( 104 buildPhases = (
97 3C0F0F681EF3781E000EADDB /* Sources */, 105 3C0F0F681EF3781E000EADDB /* Sources */,
98 3C0F0F691EF3781E000EADDB /* Frameworks */, 106 3C0F0F691EF3781E000EADDB /* Frameworks */,
@@ -102,9 +110,9 @@
102 ); 110 );
103 dependencies = ( 111 dependencies = (
104 ); 112 );
105 name = MoonParser; 113 name = MoonPlusPlus;
106 productName = PegtlStudy; 114 productName = PegtlStudy;
107 productReference = 3C0F0F6C1EF3781E000EADDB /* MoonParser */; 115 productReference = 3C0F0F6C1EF3781E000EADDB /* MoonPlusPlus */;
108 productType = "com.apple.product-type.tool"; 116 productType = "com.apple.product-type.tool";
109 }; 117 };
110/* End PBXNativeTarget section */ 118/* End PBXNativeTarget section */
@@ -122,7 +130,7 @@
122 }; 130 };
123 }; 131 };
124 }; 132 };
125 buildConfigurationList = 3C0F0F671EF3781E000EADDB /* Build configuration list for PBXProject "MoonParser" */; 133 buildConfigurationList = 3C0F0F671EF3781E000EADDB /* Build configuration list for PBXProject "MoonPlusPlus" */;
126 compatibilityVersion = "Xcode 3.2"; 134 compatibilityVersion = "Xcode 3.2";
127 developmentRegion = en; 135 developmentRegion = en;
128 hasScannedForEncodings = 0; 136 hasScannedForEncodings = 0;
@@ -135,7 +143,7 @@
135 projectDirPath = ""; 143 projectDirPath = "";
136 projectRoot = ""; 144 projectRoot = "";
137 targets = ( 145 targets = (
138 3C0F0F6B1EF3781E000EADDB /* MoonParser */, 146 3C0F0F6B1EF3781E000EADDB /* MoonPlusPlus */,
139 ); 147 );
140 }; 148 };
141/* End PBXProject section */ 149/* End PBXProject section */
@@ -145,12 +153,12 @@
145 isa = PBXSourcesBuildPhase; 153 isa = PBXSourcesBuildPhase;
146 buildActionMask = 2147483647; 154 buildActionMask = 2147483647;
147 files = ( 155 files = (
148 3C6FFA341F16F97400541BCA /* moon_parser.cpp in Sources */, 156 3C1C21F12368322900147A19 /* parser.cpp in Sources */,
149 3C3B1C601F1EF0AB0052A206 /* moon_ast.cpp in Sources */, 157 3C1C21EE2368322900147A19 /* ast.cpp in Sources */,
150 3C54E26C234C80CC00202423 /* moonc.cpp in Sources */, 158 3C1C21F32368322900147A19 /* moonc.cpp in Sources */,
151 3C6FFA351F16F97400541BCA /* parser.cpp in Sources */, 159 3C1C21EF2368322900147A19 /* moon_ast.cpp in Sources */,
152 3C6FFA331F16F97400541BCA /* ast.cpp in Sources */, 160 3C1C21F02368322900147A19 /* moon_compiler.cpp in Sources */,
153 3C1C21CD2367E69100147A19 /* moon_compiler.cpp in Sources */, 161 3C1C21F22368322900147A19 /* moon_parser.cpp in Sources */,
154 ); 162 );
155 runOnlyForDeploymentPostprocessing = 0; 163 runOnlyForDeploymentPostprocessing = 0;
156 }; 164 };
@@ -291,7 +299,7 @@
291/* End XCBuildConfiguration section */ 299/* End XCBuildConfiguration section */
292 300
293/* Begin XCConfigurationList section */ 301/* Begin XCConfigurationList section */
294 3C0F0F671EF3781E000EADDB /* Build configuration list for PBXProject "MoonParser" */ = { 302 3C0F0F671EF3781E000EADDB /* Build configuration list for PBXProject "MoonPlusPlus" */ = {
295 isa = XCConfigurationList; 303 isa = XCConfigurationList;
296 buildConfigurations = ( 304 buildConfigurations = (
297 3C0F0F711EF3781E000EADDB /* Debug */, 305 3C0F0F711EF3781E000EADDB /* Debug */,
@@ -300,7 +308,7 @@
300 defaultConfigurationIsVisible = 0; 308 defaultConfigurationIsVisible = 0;
301 defaultConfigurationName = Release; 309 defaultConfigurationName = Release;
302 }; 310 };
303 3C0F0F731EF3781E000EADDB /* Build configuration list for PBXNativeTarget "MoonParser" */ = { 311 3C0F0F731EF3781E000EADDB /* Build configuration list for PBXNativeTarget "MoonPlusPlus" */ = {
304 isa = XCConfigurationList; 312 isa = XCConfigurationList;
305 buildConfigurations = ( 313 buildConfigurations = (
306 3C0F0F741EF3781E000EADDB /* Debug */, 314 3C0F0F741EF3781E000EADDB /* Debug */,
diff --git a/MoonParser.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/MoonPlus.xcodeproj/project.xcworkspace/contents.xcworkspacedata
index 1effa34..426e6c6 100644
--- a/MoonParser.xcodeproj/project.xcworkspace/contents.xcworkspacedata
+++ b/MoonPlus.xcodeproj/project.xcworkspace/contents.xcworkspacedata
@@ -2,6 +2,6 @@
2<Workspace 2<Workspace
3 version = "1.0"> 3 version = "1.0">
4 <FileRef 4 <FileRef
5 location = "self:/Users/Jin/Workspace/PegtlStudy/MoonParser.xcodeproj"> 5 location = "self:/Users/Jin/Workspace/MoonParser/MoonPlusPlus.xcodeproj">
6 </FileRef> 6 </FileRef>
7</Workspace> 7</Workspace>
diff --git a/MoonParser.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/MoonPlus.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
index 18d9810..18d9810 100644
--- a/MoonParser.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
+++ b/MoonPlus.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
diff --git a/makefile b/makefile
new file mode 100644
index 0000000..5042b08
--- /dev/null
+++ b/makefile
@@ -0,0 +1,236 @@
1#### PROJECT SETTINGS ####
2# The name of the executable to be created
3BIN_NAME := moonc
4# Compiler used
5CXX ?= g++
6# Extension of source files used in the project
7SRC_EXT = cpp
8# Path to the source directory, relative to the makefile
9SRC_PATH = ./src
10# Space-separated pkg-config libraries used by this project
11LIBS =
12# General compiler flags
13COMPILE_FLAGS = -std=c++17 -Wall -Wextra -g
14# Additional release-specific flags
15RCOMPILE_FLAGS = -D NDEBUG -O3
16# Additional debug-specific flags
17DCOMPILE_FLAGS = -D DEBUG
18# Add additional include paths
19INCLUDES = -I $(SRC_PATH)
20# General linker settings
21LINK_FLAGS =
22# Additional release-specific linker settings
23RLINK_FLAGS =
24# Additional debug-specific linker settings
25DLINK_FLAGS =
26# Destination directory, like a jail or mounted system
27DESTDIR = /
28# Install path (bin/ is appended automatically)
29INSTALL_PREFIX = usr/local
30# Test
31TEST_INPUT = ./spec/inputs
32TEST_OUTPUT = ./spec/outputs
33#### END PROJECT SETTINGS ####
34
35# Optionally you may move the section above to a separate config.mk file, and
36# uncomment the line below
37# include config.mk
38
39# Generally should not need to edit below this line
40
41# Obtains the OS type, either 'Darwin' (OS X) or 'Linux'
42UNAME_S:=$(shell uname -s)
43
44# Function used to check variables. Use on the command line:
45# make print-VARNAME
46# Useful for debugging and adding features
47print-%: ; @echo $*=$($*)
48
49# Shell used in this makefile
50# bash is used for 'echo -en'
51SHELL = /bin/bash
52# Clear built-in rules
53.SUFFIXES:
54# Programs for installation
55INSTALL = install
56INSTALL_PROGRAM = $(INSTALL)
57INSTALL_DATA = $(INSTALL) -m 644
58
59# Append pkg-config specific libraries if need be
60ifneq ($(LIBS),)
61 COMPILE_FLAGS += $(shell pkg-config --cflags $(LIBS))
62 LINK_FLAGS += $(shell pkg-config --libs $(LIBS))
63endif
64
65# Verbose option, to output compile and link commands
66export V := false
67export CMD_PREFIX := @
68ifeq ($(V),true)
69 CMD_PREFIX :=
70endif
71
72# Combine compiler and linker flags
73release: export CXXFLAGS := $(CXXFLAGS) $(COMPILE_FLAGS) $(RCOMPILE_FLAGS)
74release: export LDFLAGS := $(LDFLAGS) $(LINK_FLAGS) $(RLINK_FLAGS)
75debug: export CXXFLAGS := $(CXXFLAGS) $(COMPILE_FLAGS) $(DCOMPILE_FLAGS)
76debug: export LDFLAGS := $(LDFLAGS) $(LINK_FLAGS) $(DLINK_FLAGS)
77
78# Build and output paths
79release: export BUILD_PATH := build/release
80release: export BIN_PATH := bin/release
81debug: export BUILD_PATH := build/debug
82debug: export BIN_PATH := bin/debug
83install: export BIN_PATH := bin/release
84
85# Find all source files in the source directory, sorted by most
86# recently modified
87ifeq ($(UNAME_S),Darwin)
88 SOURCES = $(shell find $(SRC_PATH) -name '*.$(SRC_EXT)' | sort -k 1nr | cut -f2-)
89else
90 SOURCES = $(shell find $(SRC_PATH) -name '*.$(SRC_EXT)' -printf '%T@\t%p\n' \
91 | sort -k 1nr | cut -f2-)
92endif
93
94# fallback in case the above fails
95rwildcard = $(foreach d, $(wildcard $1*), $(call rwildcard,$d/,$2) \
96 $(filter $(subst *,%,$2), $d))
97ifeq ($(SOURCES),)
98 SOURCES := $(call rwildcard, $(SRC_PATH), *.$(SRC_EXT))
99endif
100
101# Set the object file names, with the source directory stripped
102# from the path, and the build path prepended in its place
103OBJECTS = $(SOURCES:$(SRC_PATH)/%.$(SRC_EXT)=$(BUILD_PATH)/%.o)
104# Set the dependency files that will be used to add header dependencies
105DEPS = $(OBJECTS:.o=.d)
106
107# Macros for timing compilation
108ifeq ($(UNAME_S),Darwin)
109 CUR_TIME = awk 'BEGIN{srand(); print srand()}'
110 TIME_FILE = $(dir $@).$(notdir $@)_time
111 START_TIME = $(CUR_TIME) > $(TIME_FILE)
112 END_TIME = read st < $(TIME_FILE) ; \
113 $(RM) $(TIME_FILE) ; \
114 st=$$((`$(CUR_TIME)` - $$st)) ; \
115 echo $$st
116else
117 TIME_FILE = $(dir $@).$(notdir $@)_time
118 START_TIME = date '+%s' > $(TIME_FILE)
119 END_TIME = read st < $(TIME_FILE) ; \
120 $(RM) $(TIME_FILE) ; \
121 st=$$((`date '+%s'` - $$st - 86400)) ; \
122 echo `date -u -d @$$st '+%H:%M:%S'`
123endif
124
125# Version macros
126# Comment/remove this section to remove versioning
127USE_VERSION := false
128# If this isn't a git repo or the repo has no tags, git describe will return non-zero
129ifeq ($(shell git describe > /dev/null 2>&1 ; echo $$?), 0)
130 USE_VERSION := true
131 VERSION := $(shell git describe --tags --long --dirty --always | \
132 sed 's/v\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)-\?.*-\([0-9]*\)-\(.*\)/\1 \2 \3 \4 \5/g')
133 VERSION_MAJOR := $(word 1, $(VERSION))
134 VERSION_MINOR := $(word 2, $(VERSION))
135 VERSION_PATCH := $(word 3, $(VERSION))
136 VERSION_REVISION := $(word 4, $(VERSION))
137 VERSION_HASH := $(word 5, $(VERSION))
138 VERSION_STRING := \
139 "$(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_PATCH).$(VERSION_REVISION)-$(VERSION_HASH)"
140 override CXXFLAGS := $(CXXFLAGS) \
141 -D VERSION_MAJOR=$(VERSION_MAJOR) \
142 -D VERSION_MINOR=$(VERSION_MINOR) \
143 -D VERSION_PATCH=$(VERSION_PATCH) \
144 -D VERSION_REVISION=$(VERSION_REVISION) \
145 -D VERSION_HASH=\"$(VERSION_HASH)\"
146endif
147
148# Standard, non-optimized release build
149.PHONY: release
150release: dirs
151ifeq ($(USE_VERSION), true)
152 @echo "Beginning release build v$(VERSION_STRING)"
153else
154 @echo "Beginning release build"
155endif
156 @$(START_TIME)
157 @$(MAKE) all --no-print-directory
158 @echo -n "Total build time: "
159 @$(END_TIME)
160
161# Debug build for gdb debugging
162.PHONY: debug
163debug: dirs
164ifeq ($(USE_VERSION), true)
165 @echo "Beginning debug build v$(VERSION_STRING)"
166else
167 @echo "Beginning debug build"
168endif
169 @$(START_TIME)
170 @$(MAKE) all --no-print-directory
171 @echo -n "Total build time: "
172 @$(END_TIME)
173
174# Create the directories used in the build
175.PHONY: dirs
176dirs:
177 @echo "Creating directories"
178 @mkdir -p $(dir $(OBJECTS))
179 @mkdir -p $(BIN_PATH)
180 @mkdir -p $(TEST_OUTPUT)
181
182# Installs to the set path
183.PHONY: install
184install:
185 @echo "Installing to $(DESTDIR)$(INSTALL_PREFIX)/bin"
186 @$(INSTALL_PROGRAM) $(BIN_PATH)/$(BIN_NAME) $(DESTDIR)$(INSTALL_PREFIX)/bin
187
188# Uninstalls the program
189.PHONY: uninstall
190uninstall:
191 @echo "Removing $(DESTDIR)$(INSTALL_PREFIX)/bin/$(BIN_NAME)"
192 @$(RM) $(DESTDIR)$(INSTALL_PREFIX)/bin/$(BIN_NAME)
193
194# Removes all build files
195.PHONY: clean
196clean:
197 @echo "Deleting $(BIN_NAME) symlink"
198 @$(RM) $(BIN_NAME)
199 @echo "Deleting directories"
200 @$(RM) -r build
201 @$(RM) -r bin
202 @echo "Deleting generated Lua codes"
203 @$(RM) -r $(TEST_OUTPUT)
204
205# Test Moonscript compiler
206.PHONY: test
207test: release
208 @echo "Compiling Moonscript codes..."
209 @./$(BIN_NAME) $(TEST_INPUT)/*.moon -a -s -t $(TEST_OUTPUT)
210
211# Main rule, checks the executable and symlinks to the output
212all: $(BIN_PATH)/$(BIN_NAME)
213 @echo "Making symlink: $(BIN_NAME) -> $<"
214 @$(RM) $(BIN_NAME)
215 @ln -s $(BIN_PATH)/$(BIN_NAME) $(BIN_NAME)
216
217# Link the executable
218$(BIN_PATH)/$(BIN_NAME): $(OBJECTS)
219 @echo "Linking: $@"
220 @$(START_TIME)
221 $(CMD_PREFIX)$(CXX) $(OBJECTS) $(LDFLAGS) -o $@
222 @echo -en "\t Link time: "
223 @$(END_TIME)
224
225# Add dependency files, if they exist
226-include $(DEPS)
227
228# Source file rules
229# After the first compilation they will be joined with the rules from the
230# dependency files to provide header dependencies
231$(BUILD_PATH)/%.o: $(SRC_PATH)/%.$(SRC_EXT)
232 @echo "Compiling: $< -> $@"
233 @$(START_TIME)
234 $(CMD_PREFIX)$(CXX) $(CXXFLAGS) $(INCLUDES) -MP -MMD -c $< -o $@
235 @echo -en "\t Compile time: "
236 @$(END_TIME)
diff --git a/spec/inputs/assign.moon b/spec/inputs/assign.moon
new file mode 100644
index 0000000..1e5e7a6
--- /dev/null
+++ b/spec/inputs/assign.moon
@@ -0,0 +1,30 @@
1
2->
3 joop = 2302
4
5 (hi) ->
6 d = 100
7 hi = 1021
8
9 a,b,c,d = 1,2,3,4
10
11 hello[232], (5+5)[121], hello, x[99] = 100, 200, 300
12
13 joop = 12
14
15joop = 2345
16
17a, b = if hello
18 "hello"
19else
20 "nothing", "yeah"
21
22
23a, b = if hello
24 if yeah then "one", "two" else "mmhh"
25else
26 print "the other"
27 "nothing", "yeah"
28
29
30
diff --git a/spec/inputs/bubbling.moon b/spec/inputs/bubbling.moon
new file mode 100644
index 0000000..d1004f9
--- /dev/null
+++ b/spec/inputs/bubbling.moon
@@ -0,0 +1,28 @@
1
2-- vararg bubbling
3f = (...) -> #{...}
4
5dont_bubble = ->
6 [x for x in ((...)-> print ...)("hello")]
7
8k = [x for x in ((...)-> print ...)("hello")]
9
10j = for i=1,10
11 (...) -> print ...
12
13-- bubble me
14
15m = (...) ->
16 [x for x in *{...} when f(...) > 4]
17
18x = for i in *{...} do i
19y = [x for x in *{...}]
20z = [x for x in hallo when f(...) > 4]
21
22
23a = for i=1,10 do ...
24
25b = for i=1,10
26 -> print ...
27
28
diff --git a/spec/inputs/class.moon b/spec/inputs/class.moon
new file mode 100644
index 0000000..9a98055
--- /dev/null
+++ b/spec/inputs/class.moon
@@ -0,0 +1,213 @@
1
2class Hello
3 new: (@test, @world) =>
4 print "creating object.."
5 hello: =>
6 print @test, @world
7 __tostring: => "hello world"
8
9x = Hello 1,2
10x\hello()
11
12print x
13
14class Simple
15 cool: => print "cool"
16
17class Yikes extends Simple
18 new: => print "created hello"
19
20x = Yikes()
21x\cool()
22
23
24class Hi
25 new: (arg) =>
26 print "init arg", arg
27
28 cool: (num) =>
29 print "num", num
30
31
32class Simple extends Hi
33 new: => super "man"
34 cool: => super 120302
35
36x = Simple()
37x\cool()
38
39print x.__class == Simple
40
41
42class Okay
43 -- what is going on
44 something: 20323
45 -- yeaha
46
47
48class Biggie extends Okay
49 something: =>
50 super 1,2,3,4
51 super.something another_self, 1,2,3,4
52 assert super == Okay
53
54
55class Yeah
56 okay: =>
57 super\something 1,2,3,4
58
59
60class What
61 something: => print "val:", @val
62
63class Hello extends What
64 val: 2323
65 something: => super\something
66
67with Hello!
68 x = \something!
69 print x
70 x!
71
72class CoolSuper
73 hi: =>
74 super(1,2,3,4) 1,2,3,4
75 super.something 1,2,3,4
76 super.something(1,2,3,4).world
77 super\yeah"world".okay hi, hi, hi
78 something.super
79 super.super.super.super
80 super\hello
81 nil
82
83
84-- selfing
85x = @hello
86x = @@hello
87
88@hello "world"
89@@hello "world"
90
91@@one @@two(4,5) @three, @four
92
93xx = (@hello, @@world, cool) ->
94
95
96-- class properties
97class ClassMan
98 @yeah: 343
99 blue: =>
100 @hello: 3434, @world: 23423
101 green: =>
102 @red: =>
103
104
105x = @
106y = @@
107
108@ something
109
110@@ something
111
112@ = @ + @ / @
113
114@ = 343
115@.hello 2,3,4
116
117hello[@].world
118
119
120class Whacko
121 @hello
122 if something
123 print "hello world"
124
125 hello = "world"
126 @another = "day"
127
128 print "yeah" if something -- this is briken
129
130
131print "hello"
132
133yyy = ->
134 class Cool
135 nil
136
137
138--
139
140class a.b.c.D
141 nil
142
143
144class a.b["hello"]
145 nil
146
147class (-> require "moon")!.Something extends Hello.World
148 nil
149
150--
151
152a = class
153b = class Something
154c = class Something extends Hello
155d = class extends World
156
157print (class WhatsUp).__name
158
159--
160
161export ^
162class Something
163 nil
164
165
166--
167
168-- hoisting
169class Something
170 val = 23
171 {:insert} = table
172 new: => print insert, val -- prints nil 23
173
174--
175
176class X
177 new: hi
178
179
180--
181
182class Cool extends Thing
183 dang: =>
184 {
185 hello: -> super!
186 world: -> super.one
187 }
188
189--
190
191class Whack extends Thing
192 dang: do_something =>
193 super!
194
195---
196
197class Wowha extends Thing
198 @butt: ->
199 super!
200 super.hello
201 super\hello!
202 super\hello
203
204
205 @zone: cool {
206 ->
207 super!
208 super.hello
209 super\hello!
210 super\hello
211 }
212
213nil
diff --git a/spec/inputs/comprehension.moon b/spec/inputs/comprehension.moon
new file mode 100644
index 0000000..1609d79
--- /dev/null
+++ b/spec/inputs/comprehension.moon
@@ -0,0 +1,52 @@
1
2-- see lists.moon for list comprehension tests
3
4items = {1,2,3,4,5,6}
5out = {k,k*2 for k in items}
6
7
8x = hello: "world", okay: 2323
9
10copy = {k,v for k,v in pairs x when k != "okay"}
11
12--
13
14{ unpack(x) for x in yes }
15{ unpack(x) for x in *yes }
16
17{ xxxx for x in yes }
18{ unpack [a*i for i, a in ipairs x] for x in *{{1,2}, {3,4}} }
19
20
21--
22
23n1 = [i for i=1,10]
24n2 = [i for i=1,10 when i % 2 == 1]
25
26aa = [{x,y} for x=1,10 for y=5,14]
27bb = [y for thing in y for i=1,10]
28cc = [y for i=1,10 for thing in y]
29dd = [y for i=1,10 when cool for thing in y when x > 3 when c + 3]
30
31{"hello", "world" for i=1,10}
32
33--
34
35j = [a for {a,b,c} in things]
36k = [a for {a,b,c} in *things]
37i = [hello for {:hello, :world} in *things]
38
39hj = {a,c for {a,b,c} in things}
40hk = {a,c for {a,b,c} in *things}
41hi = {hello,world for {:hello, :world} in *things}
42
43ok(a,b,c) for {a,b,c} in things
44
45--
46
47[item for item in *items[1 + 2,3+4]]
48[item for item in *items[hello! * 4, 2 - thing[4]]]
49
50
51
52nil
diff --git a/spec/inputs/cond.moon b/spec/inputs/cond.moon
new file mode 100644
index 0000000..18e42b9
--- /dev/null
+++ b/spec/inputs/cond.moon
@@ -0,0 +1,190 @@
1
2you_cool = false
3
4if cool
5 if you_cool
6 one
7 else if eatdic
8 yeah
9 else
10 two
11 three
12else
13 no
14
15if cool then no
16if cool then no else yes
17
18if cool then wow cool else
19 noso cool
20
21if working
22 if cool then if cool then okay else what else nah
23
24
25if yeah then no day elseif cool me then okay ya else u way
26if yeah then no dad else if cool you then okay bah else p way
27
28
29if (->)() then what ever
30
31if nil then flip me else
32 it be,rad
33
34
35if things great then no way elseif okay sure
36 what here
37
38
39if things then no chance
40elseif okay
41 what now
42
43
44if things
45 yes man
46elseif okay person then hi there else hmm sure
47
48if lets go
49 print "greetings"
50elseif "just us"
51 print "will smith" else show 5555555
52
53--
54
55if something = 10
56 print something
57else
58 print "else"
59
60hello = if something = 10
61 print something
62else
63 print "else"
64
65
66hello = 5 + if something = 10
67 print something
68
69---
70
71z = false
72
73if false
74 one
75elseif x = true
76 two
77elseif z = true
78 three
79else
80 four
81
82
83out = if false
84 one
85elseif x = true
86 two
87elseif z = true
88 three
89else
90 four
91
92kzy = ->
93 if something = true
94 1
95 elseif another = false
96 2
97
98---
99
100unless true
101 print "cool!"
102
103unless true and false
104 print "cool!"
105
106unless false then print "cool!"
107unless false then print "cool!" else print "no way!"
108
109unless nil
110 print "hello"
111else
112 print "world"
113
114--
115
116x = unless true
117 print "cool!"
118
119x = unless true and false
120 print "cool!"
121
122y = unless false then print "cool!"
123y = unless false then print "cool!" else print "no way!"
124
125z = unless nil
126 print "hello"
127else
128 print "world"
129
130print unless true
131 print "cool!"
132
133print unless true and false
134 print "cool!"
135
136print unless false then print "cool!"
137print unless false then print "cool!" else print "no way!"
138
139print unless nil
140 print "hello"
141else
142 print "world"
143
144--
145
146print "hello" unless value
147
148dddd = {1,2,3} unless value
149
150
151--
152
153do
154 j = 100
155 unless j = hi!
156 error "not j!"
157
158----------------
159
160a = 12
161a,c,b = "cool" if something
162
163
164
165---
166
167j = if 1
168 if 2
169 3
170else 6
171
172
173m = if 1
174
175
176
177 if 2
178
179
180 3
181
182
183else 6
184
185
186
187nil
188
189
190
diff --git a/spec/inputs/destructure.moon b/spec/inputs/destructure.moon
new file mode 100644
index 0000000..beb79d6
--- /dev/null
+++ b/spec/inputs/destructure.moon
@@ -0,0 +1,100 @@
1
2do
3 {a, b} = hello
4
5 {{a}, b, {c}} = hello
6
7 { :hello, :world } = value
8
9do
10 { yes: no, thing } = world
11
12 {:a,:b,:c,:d} = yeah
13
14 {a} = one, two
15 {b}, c = one
16 {d}, e = one, two
17
18 x, {y} = one, two
19
20 xx, yy = 1, 2
21 {yy, xx} = {xx, yy}
22
23 {a, :b, c, :d, e, :f, g} = tbl
24
25---
26
27do
28 futurists =
29 sculptor: "Umberto Boccioni"
30 painter: "Vladimir Burliuk"
31 poet:
32 name: "F.T. Marinetti"
33 address: {
34 "Via Roma 42R"
35 "Bellagio, Italy 22021"
36 }
37
38 {poet: {:name, address: {street, city}}} = futurists
39
40--
41
42do
43 { @world } = x
44 { a.b, c.y, func!.z } = x
45
46 { world: @world } = x
47
48--
49
50do
51 thing = {{1,2}, {3,4}}
52
53 for {x,y} in *thing
54 print x,y
55
56
57--
58
59do
60 with {a,b} = thing
61 print a, b
62
63
64--
65
66do
67 thing = nil
68 if {a} = thing
69 print a
70 else
71 print "nothing"
72
73 thang = {1,2}
74 if {a,b} = thang
75 print a,b
76
77 if {a,b} = thing
78 print a,b
79 elseif {c,d} = thang
80 print c,d
81 else
82 print "NO"
83
84--
85
86do
87 z = "yeah"
88 {a,b,c} = z
89
90do
91 {a,b,c} = z
92
93(z) ->
94 {a,b,c} = z
95
96do
97 z = "oo"
98 (k) ->
99 {a,b,c} = z
100
diff --git a/spec/inputs/do.moon b/spec/inputs/do.moon
new file mode 100644
index 0000000..334e68f
--- /dev/null
+++ b/spec/inputs/do.moon
@@ -0,0 +1,27 @@
1
2do
3 print "hello"
4 print "world"
5
6x = do
7 print "hello"
8 print "world"
9
10y = do
11 things = "shhh"
12 -> "hello: " .. things
13
14-> if something then do "yeah"
15
16t = {
17 y: do
18 number = 100
19 (x) -> x + number
20}
21
22(y=(do
23 x = 10 + 2
24 x), k=do
25 "nothing") -> do
26 "uhhh"
27
diff --git a/spec/inputs/export.moon b/spec/inputs/export.moon
new file mode 100644
index 0000000..0a56379
--- /dev/null
+++ b/spec/inputs/export.moon
@@ -0,0 +1,77 @@
1
2do
3 export a,b,c = 223, 343
4 export cool = "dad"
5
6do
7 export class Something
8 umm: "cool"
9
10do
11 export a,b,c
12 a,b,c,d = "hello"
13
14
15do
16 What = if this
17 232
18 else
19 4343
20
21 export ^
22
23 another = 3434
24 Another = 7890
25
26 if inner then Yeah = "10000"
27
28 What = if this
29 232
30 else
31 4343
32
33
34do
35 export *
36
37 What = if this
38 232
39 else
40 4343
41
42 x,y,z = 1,2,3
43
44 y = ->
45 hallo = 3434
46
47 with tmp
48 j = 2000
49
50
51do
52 export *
53 x = 3434
54 if y then
55 x = 10
56
57do
58 export *
59 if y then
60 x = 10
61 x = 3434
62
63do
64 do
65 export *
66
67 k = 1212
68
69 do
70 h = 100
71
72 y = ->
73 h = 100
74 k = 100
75
76 h = 100
77
diff --git a/spec/inputs/funcs.moon b/spec/inputs/funcs.moon
new file mode 100644
index 0000000..08a29b6
--- /dev/null
+++ b/spec/inputs/funcs.moon
@@ -0,0 +1,158 @@
1
2
3x = -> print what
4
5->
6
7-> -> ->
8
9go to the barn
10
11open -> the -> door
12
13open ->
14 the door
15 hello = ->
16 my func
17
18h = -> hi
19
20eat ->, world
21
22
23(->)()
24
25x = (...) ->
26
27hello!
28hello.world!
29
30hello!.something
31what!["ofefe"]
32
33what! the! heck!
34
35(a,b,c,d,e) ->
36
37(a,a,a,a,a) ->
38 print a
39
40(x=23023) ->
41
42(x=(y=()->) ->) ->
43
44(x = if something then yeah else no) ->
45
46something = (hello=100, world=(x=[[yeah cool]])-> print "eat rice") ->
47 print hello
48
49(x, y) =>
50(@x, @y) =>
51(x=1) =>
52(@x=1,y,@z="hello world") =>
53
54
55x -> return
56y -> return 1
57z -> return 1, "hello", "world"
58k -> if yes then return else return
59
60-> real_name if something
61
62--
63
64d(
65 ->
66 print "hello world"
67 10
68)
69
70
71
72d(
73 1,2,3
74 4
75 5
76 6
77
78 if something
79 print "okay"
80 10
81
82 10,20
83)
84
85
86f(
87
88 )(
89
90 )(
91 what
92 )(->
93 print "srue"
94 123)
95
96--
97
98x = (a,
99 b) ->
100 print "what"
101
102
103y = (a="hi",
104 b=23) ->
105 print "what"
106
107z = (
108 a="hi",
109 b=23) ->
110 print "what"
111
112
113j = (f,g,m,
114 a="hi",
115 b=23
116) ->
117 print "what"
118
119
120y = (a="hi",
121 b=23,
122 ...) ->
123 print "what"
124
125
126y = (a="hi",
127 b=23,
128 ...
129) ->
130 print "what"
131
132--
133
134args = (a
135 b) ->
136 print "what"
137
138
139args = (a="hi"
140 b=23) ->
141 print "what"
142
143args = (
144 a="hi"
145 b=23) ->
146 print "what"
147
148
149args = (f,g,m
150 a="hi"
151 b=23
152) ->
153 print "what"
154
155
156
157
158nil
diff --git a/spec/inputs/import.moon b/spec/inputs/import.moon
new file mode 100644
index 0000000..d86d724
--- /dev/null
+++ b/spec/inputs/import.moon
@@ -0,0 +1,48 @@
1
2
3import hello from yeah
4import hello, world from table["cool"]
5
6import a, \b, c from items
7
8
9import master, \ghost from find "mytable"
10
11
12a, yumm = 3434, "hello"
13
14
15_table_0 = 232
16
17import something from a table
18
19
20if indent
21 import okay, \well from tables[100]
22
23do
24 import a, b, c from z
25
26do
27 import a,
28 b, c from z
29
30do
31 import a
32 b
33 c from z
34
35do
36 import
37 a
38 b
39 c from z
40
41
42do
43 import
44 a
45 b
46 c
47 from z
48
diff --git a/spec/inputs/lists.moon b/spec/inputs/lists.moon
new file mode 100644
index 0000000..c119185
--- /dev/null
+++ b/spec/inputs/lists.moon
@@ -0,0 +1,72 @@
1
2hi = [x*2 for _, x in ipairs{1,2,3,4}]
3
4items = {1,2,3,4,5,6}
5
6[z for z in ipairs items when z > 4]
7
8rad = [{a} for a in ipairs {
9 1,2,3,4,5,6,
10} when good_number a]
11
12
13[z for z in items for j in list when z > 4]
14
15require "util"
16
17dump = (x) -> print util.dump x
18
19range = (count) ->
20 i = 0
21 return coroutine.wrap ->
22 while i < count
23 coroutine.yield i
24 i = i + 1
25
26dump [x for x in range 10]
27dump [{x, y} for x in range 5 when x > 2 for y in range 5]
28
29things = [x + y for x in range 10 when x > 5 for y in range 10 when y > 7]
30
31print x,y for x in ipairs{1,2,4} for y in ipairs{1,2,3} when x != 2
32
33print "hello", x for x in items
34
35[x for x in x]
36x = [x for x in x]
37
38print x,y for x in ipairs{1,2,4} for y in ipairs{1,2,3} when x != 2
39
40double = [x*2 for x in *items]
41
42print x for x in *double
43
44cut = [x for x in *items when x > 3]
45
46hello = [x + y for x in *items for y in *items]
47
48print z for z in *hello
49
50
51-- slice
52x = {1, 2, 3, 4, 5, 6, 7}
53print y for y in *x[2,-5,2]
54print y for y in *x[,3]
55print y for y in *x[2,]
56print y for y in *x[,,2]
57print y for y in *x[2,,2]
58
59a, b, c = 1, 5, 2
60print y for y in *x[a,b,c]
61
62
63normal = (hello) ->
64 [x for x in yeah]
65
66
67test = x 1,2,3,4,5
68print thing for thing in *test
69
70-> a = b for row in *rows
71
72
diff --git a/spec/inputs/literals.moon b/spec/inputs/literals.moon
new file mode 100644
index 0000000..c3a24a6
--- /dev/null
+++ b/spec/inputs/literals.moon
@@ -0,0 +1,46 @@
1
2
3121
4121.2323
5121.2323e-1
6121.2323e13434
72323E34
80x12323
9
100xfF2323
110xabcdef
120xABCDEF
13
14.2323
15.2323e-1
16.2323e13434
17
18
191LL
201ULL
219332LL
229332
230x2aLL
240x2aULL
25
26[[ hello world ]]
27
28[=[ hello world ]=]
29[====[ hello world ]====]
30
31"another world"
32
33'what world'
34
35
36"
37hello world
38"
39
40'yeah
41what is going on
42here is something cool'
43
44
45nil
46
diff --git a/spec/inputs/local.moon b/spec/inputs/local.moon
new file mode 100644
index 0000000..fec78b1
--- /dev/null
+++ b/spec/inputs/local.moon
@@ -0,0 +1,94 @@
1
2do
3 local a
4 local a,b,c
5
6 b,g = 23232
7
8
9do
10 x = 1212
11 something = ->
12 local x
13 x = 1212
14
15do
16 local *
17 y = 2323
18 z = 2323
19
20do
21 local *
22 print "Nothing Here!"
23
24do
25 local ^
26 x = 3434
27 y = 3434
28 X = 3434
29 Y = "yeah"
30
31do
32 local ^
33 x,y = "a", "b"
34
35do
36 local *
37 x,y = "a", "b"
38
39
40do
41 local *
42 if something
43 x = 2323
44
45do
46 local *
47 do
48 x = "one"
49
50 x = 100
51
52 do
53 x = "two"
54
55do
56 local *
57 k = if what
58 10
59 x = 100
60
61 {:a,:b, :c} = y
62
63
64do
65 local *
66
67 a = 100
68 print "hi"
69 b = 200
70
71 local *
72 c = 100
73 print "hi"
74 d = 200
75 d = 2323
76
77
78do
79 local ^
80 lowercase = 5
81 Uppercase = 3
82
83 class One
84 Five = 6
85
86 class Two
87 class No
88
89do
90 local *
91 -- this generates a nil value in the body
92 for a in *{} do a
93
94g = 2323 -- test if anything leaked
diff --git a/spec/inputs/loops.moon b/spec/inputs/loops.moon
new file mode 100644
index 0000000..a704e56
--- /dev/null
+++ b/spec/inputs/loops.moon
@@ -0,0 +1,133 @@
1
2for x=1,10
3 print "yeah"
4
5for x=1,#something
6 print "yeah"
7
8for y=100,60,-3
9 print "count down", y
10
11for a=1,10 do print "okay"
12
13for a=1,10
14 for b = 2,43
15 print a,b
16
17for i in iter
18 for j in yeah
19 x = 343 + i + j
20 print i, j
21
22for x in *something
23 print x
24
25for k,v in pairs hello do print k,v
26
27for x in y, z
28 print x
29
30for x in y, z, k
31 print x
32
33
34x = ->
35 for x in y
36 y
37
38hello = {1,2,3,4,5}
39
40x = for y in *hello
41 if y % 2 == 0
42 y
43
44x = ->
45 for x in *hello
46 y
47
48t = for i=10,20 do i * 2
49
50hmm = 0
51y = for j = 3,30, 8
52 hmm += 1
53 j * hmm
54
55->
56 for k=10,40
57 "okay"
58
59->
60 return for k=10,40
61 "okay"
62
63while true do print "name"
64
65while 5 + 5
66 print "okay world"
67 working man
68
69while also do
70 i work too
71 "okay"
72
73i = 0
74x = while i < 10
75 i += 1
76
77-- values that can'e be coerced
78
79x = for thing in *3
80 y = "hello"
81
82x = for x=1,2
83 y = "hello"
84
85
86-- continue
87
88while true
89 continue if false
90 print "yes"
91 break if true
92 print "no"
93
94
95for x=1,10
96 continue if x > 3 and x < 7
97 print x
98
99
100list = for x=1,10
101 continue if x > 3 and x < 7
102 x
103
104
105for a in *{1,2,3,4,5,6}
106 continue if a == 1
107 continue if a == 3
108 print a
109
110
111
112for x=1,10
113 continue if x % 2 == 0
114 for y = 2,12
115 continue if y % 3 == 0
116
117
118while true
119 continue if false
120 break
121
122while true
123 continue if false
124 return 22
125
126--
127
128do
129 xxx = {1,2,3,4}
130 for thing in *xxx
131 print thing
132
133
diff --git a/spec/inputs/operators.moon b/spec/inputs/operators.moon
new file mode 100644
index 0000000..142ef62
--- /dev/null
+++ b/spec/inputs/operators.moon
@@ -0,0 +1,72 @@
1
2-- binary ops
3x = 1 + 3
4
5y = 1 +
6 3
7
8z = 1 +
9 3 +
10 4
11
12--
13
14k = b and c and
15 g
16
17
18h = thing and
19 ->
20 print "hello world"
21
22-- TODO: should fail, indent still set to previous line so it thinks body is
23-- indented
24i = thing or
25 ->
26 print "hello world"
27
28p = thing and
29 ->
30print "hello world"
31
32s = thing or
33 -> and 234
34
35
36--
37u = {
38 color: 1 and 2 and
39 3
40 4
41 4
42}
43
44v = {
45 color: 1 and
46 ->
47 "yeah"
48 "great"
49 oksy: 3 ^
502
51}
52
53-- parens
54
55nno = (
56 yeah + 2 )
57
58nn = (
59 yeah + 2
60)
61
62n = hello(
63 b
64) ->
65
66hello a,
67 (
68 yeah +
69 2
70 ) -
71 okay
72
diff --git a/spec/inputs/plus.moon b/spec/inputs/plus.moon
new file mode 100644
index 0000000..fdca8be
--- /dev/null
+++ b/spec/inputs/plus.moon
@@ -0,0 +1,7 @@
1
2func a\do!\end("OK")\if "abc",123
3
4res = b.function\do!\while("OK")\if "def",998
5
6c.repeat.if\then("xyz")\else res
7
diff --git a/spec/inputs/return.moon b/spec/inputs/return.moon
new file mode 100644
index 0000000..61d3dca
--- /dev/null
+++ b/spec/inputs/return.moon
@@ -0,0 +1,55 @@
1-- testing `return` propagation
2
3-> x for x in *things
4-> [x for x in *things]
5
6
7-- doesn't make sense on purpose
8do
9 return x for x in *things
10
11do
12 return [x for x in *things]
13
14do
15 return {x,y for x,y in *things}
16
17->
18 if a
19 if a
20 a
21 else
22 b
23 elseif b
24 if a
25 a
26 else
27 b
28 else
29 if a
30 a
31 else
32 b
33
34
35do
36 return if a
37 if a
38 a
39 else
40 b
41 elseif b
42 if a
43 a
44 else
45 b
46 else
47 if a
48 a
49 else
50 b
51
52-> a\b
53do a\b
54
55
diff --git a/spec/inputs/string.moon b/spec/inputs/string.moon
new file mode 100644
index 0000000..897056a
--- /dev/null
+++ b/spec/inputs/string.moon
@@ -0,0 +1,66 @@
1
2hi = "hello"
3hello = "what the heckyes"
4print hi
5
6umm = 'umm'
7
8here, another = "yeah", 'world'
9
10aye = "YU'M"
11you '"hmmm" I said'
12
13print aye, you
14
15another = [[ hello world ]]
16
17
18hi_there = [[
19 hi there
20]]
21
22well = [==[ "helo" ]==]
23
24hola = [===[
25 eat noots]===]
26
27mm = [[well trhere]]
28
29oo = ""
30
31x = "\\"
32x = "a\\b"
33x = "\\\n"
34x = "\""
35
36--
37
38a = "hello #{hello} hello"
39b = "#{hello} hello"
40c = "hello #{5+1}"
41d = "#{hello world}"
42e = "#{1} #{2} #{3}"
43
44f = [[hello #{world} world]]
45
46--
47
48a = 'hello #{hello} hello'
49b = '#{hello} hello'
50c = 'hello #{hello}'
51
52
53--
54
55"hello"
56"hello"\format 1
57"hello"\format(1,2,3)
58"hello"\format(1,2,3) 1,2,3
59
60"hello"\world!
61"hello"\format!.hello 1,2,3
62"hello"\format 1,2,3
63
64something"hello"\world!
65something "hello"\world!
66
diff --git a/spec/inputs/stub.moon b/spec/inputs/stub.moon
new file mode 100644
index 0000000..f8f6c3f
--- /dev/null
+++ b/spec/inputs/stub.moon
@@ -0,0 +1,16 @@
1
2
3x = {
4 val: 100
5 hello: =>
6 print @val
7}
8
9fn = x\val
10print fn!
11print x\val!
12
13
14-- ... should be bubbled up anon functions
15x = hello(...)\world
16
diff --git a/spec/inputs/switch.moon b/spec/inputs/switch.moon
new file mode 100644
index 0000000..3bc179b
--- /dev/null
+++ b/spec/inputs/switch.moon
@@ -0,0 +1,64 @@
1
2switch value
3 when "cool"
4 print "hello world"
5
6
7switch value
8 when "cool"
9 print "hello world"
10 else
11 print "okay rad"
12
13
14switch value
15 when "cool"
16 print "hello world"
17 when "yeah"
18 [[FFFF]] + [[MMMM]]
19 when 2323 + 32434
20 print "okay"
21 else
22 print "okay rad"
23
24out = switch value
25 when "cool" then print "hello world"
26 else print "okay rad"
27
28out = switch value
29 when "cool" then xxxx
30 when "umm" then 34340
31 else error "this failed big time"
32
33with something
34 switch \value!
35 when .okay
36 "world"
37 else
38 "yesh"
39
40fix this
41call_func switch something
42 when 1 then "yes"
43 else "no"
44
45--
46
47switch hi
48 when hello or world
49 greene
50
51--
52
53switch hi
54 when "one", "two"
55 print "cool"
56 when "dad"
57 no
58
59switch hi
60 when 3+1, hello!, (-> 4)!
61 yello
62 else
63 print "cool"
64
diff --git a/spec/inputs/syntax.moon b/spec/inputs/syntax.moon
new file mode 100644
index 0000000..854f629
--- /dev/null
+++ b/spec/inputs/syntax.moon
@@ -0,0 +1,272 @@
1#!/this/is/ignored
2
3a = 1 + 2* 3 / 6
4
5a, bunch, go, here = another, world
6
7func arg1, arg2, another, arg3
8
9here, we = () ->, yeah
10the, different = () -> approach; yeah
11
12dad()
13dad(lord)
14hello(one,two)()
15(5 + 5)(world)
16
17fun(a)(b)
18
19fun(a) b
20
21fun(a) b, bad hello
22
23hello world what are you doing here
24
25
26what(the)[3243] world, yeck heck
27
28hairy[hands][are](gross) okay okay[world]
29
30(get[something] + 5)[years]
31
32i,x = 200, 300
33
34yeah = (1 + 5) * 3
35yeah = ((1+5)*3)/2
36yeah = ((1+5)*3)/2 + i % 100
37
38whoa = (1+2) * (3+4) * (4+5)
39
40->
41 if something
42 return 1,2,4
43
44 print "hello"
45
46->
47 if hello
48 "heloo", "world"
49 else
50 no, way
51
52
53-> 1,2,34
54
55return 5 + () -> 4 + 2
56
57return 5 + (() -> 4) + 2
58
59print 5 + () ->
60 34
61 good nads
62
63
64something 'else', "ya"
65
66something'else'
67something"else"
68
69something[[hey]] * 2
70something[======[hey]======] * 2
71
72
73something'else', 2
74something"else", 2
75something[[else]], 2
76
77something 'else', 2
78something "else", 2
79something [[else]], 2
80
81here(we)"go"[12123]
82
83-- this runs
84something =
85 test: 12323
86 what: -> print "hello world"
87
88print something.test
89
90frick = hello: "world"
91
92argon =
93 num: 100
94 world: (self) ->
95 print self.num
96 return {
97 something: -> print "hi from something"
98 }
99 somethin: (self, str) ->
100 print "string is", str
101 return world: (a,b) -> print "sum", a + b
102
103something.what()
104argon\world().something()
105
106argon\somethin"200".world(1,2)
107
108x = -434
109
110x = -hello world one two
111
112hi = -"herfef"
113
114x = -[x for x in x]
115
116print "hello" if cool
117print "hello" unless cool
118print "hello" unless 1212 and 3434 -- hello
119print "hello" for i=1,10
120
121print "nutjob"
122
123if hello then 343
124
125print "what" if cool else whack
126
127arg = {...}
128
129x = (...) ->
130 dump {...}
131
132
133x = not true
134
135y = not(5+5)
136
137
138y = #"hello"
139
140x = #{#{},#{1},#{1,2}}
141
142hello, world
143
144something\hello(what) a,b
145something\hello what
146something.hello\world a,b
147something.hello\world(1,2,3) a,b
148
149
150x = 1232
151x += 10 + 3
152j -= "hello"
153y *= 2
154y /= 100
155m %= 2
156hello ..= "world"
157
158@@something += 10
159@something += 10
160
161a["hello"] += 10
162a["hello#{tostring ff}"] += 10
163a[four].x += 10
164
165x = 0
166(if ntype(v) == "fndef" then x += 1) for v in *values
167
168
169hello =
170 something: world
171 if: "hello"
172 else: 3434
173 function: "okay"
174 good: 230203
175
176
177div class: "cool"
178
1795 + what wack
180what whack + 5
181
1825 - what wack
183what whack - 5
184
185x = hello - world - something
186
187((something = with what
188 \cool 100) ->
189 print something)!
190
191if something
192 03589
193
194-- okay what about this
195
196else
197 3434
198
199
200if something
201 yeah
202
203
204elseif "ymmm"
205
206 print "cool"
207
208else
209
210 okay
211
212
213-- test names containing keywords
214x = notsomething
215y = ifsomething
216z = x and b
217z = x andb
218
219
220-- undelimited tables
221
222while 10 > something
223 something: "world"
224 print "yeah"
225
226x =
227 okay: sure
228
229yeah
230 okay: man
231 sure: sir
232
233hello "no comma"
234 yeah: dada
235 another: world
236
237hello "comma",
238 something: hello_world
239 frick: you
240
241-- creates two tables
242another hello, one,
243 two, three, four, yeah: man
244 okay: yeah
245
246--
247a += 3 - 5
248a *= 3 + 5
249a *= 3
250a >>= 3
251a <<= 3
252a /= func "cool"
253
254---
255
256x.then = "hello"
257x.while.true = "hello"
258
259--
260
261x or= "hello"
262x and= "hello"
263
264--
265
266z = a-b
267z = a -b
268z = a - b
269z = a- b
270
271
272-- cooool
diff --git a/spec/inputs/tables.moon b/spec/inputs/tables.moon
new file mode 100644
index 0000000..2bf66d7
--- /dev/null
+++ b/spec/inputs/tables.moon
@@ -0,0 +1,161 @@
1
2backpack =
3 something:
4 yeah: 200
5 they: ->
6 print "hello"
7 yor_feet"small"
8 pretty: hair
9 gold: hmm
10 yow: 1000
11
12 eat: goo
13 yeah: dudd
14
15
16start =
17 something: "cold"
18
19bathe =
20 on: "fire"
21
22another =
23 [4]: 232
24 ["good food"]: "is the best"
25
26fwip =
27 something: hello"what", number: 2323,
28 what: yo "momma", "yeah",
29 fruit: basket
30 nuts: day
31
32
33frick = hello: "world"
34
35frack, best = hello: "world", rice: 3434, "what"
36
37ya = { 1,2,3, key: 100, 343, "hello", umm: 232 }
38
39
40x = { 1,2,
41 4343, 343 ,343 }
42
43
44g, p = {
45 1,2, nowy: "yes", 3,4,
46 hey: 232, another: "day"
47}, 234
48
49annother = {
50 1,2,3
51 3,4,5
52 6,7,8
53}
54
55yeah = {
56 [232]: 3434, "helo"
57 ice: "cake"
58}
59
60-- confusing stuff...
61whatabout = {
62 hello world, another
63 what, about, now
64
65 hello"world", yeah
66 hello "world", yeah
67}
68
69x =
70 -- yeah
71 something: => "hello"
72 cool: -- umm
73 --so ething
74 bed: {
75 2323,2323
76 }
77 red: 2343 -- here
78 -- what
79 name: (node) => @value node -- here
80 -- comment me
81-- okay
82
83
84x = { :something, something: something }
85
86y = {
87 :hi, :there, :how, :you
88 :thing
89}
90
91call_me "hello", :x, :y, :z
92
93t = {
94 a: 'a'
95 [b]: 'b'
96}
97
98xam = {
99 hello: 1234
100 "hello": 12354
101 ["hello"]: 12354
102}
103
104
105kam = {
106 hello: 12
107 goodcheese:
108 "mmm"
109
110 yeah:
111 12 + 232
112
113 lets:
114 keepit going: true,
115 okay: "yeah"
116
117 more:
118 {
119 1, [x for x=1,10]
120 }
121
122 [{"one", "two"}]:
123 one_thing =>
124}
125
126-- TODO: both of these have undesirable output
127keepit going: true,
128 okay: "yeah",
129 workd: "okay"
130
131thing what:
132 "great", no:
133 "more"
134 okay: 123
135
136
137--
138thing what:
139 "great", no:
140 "more"
141okay: 123 -- a anon table
142
143
144--
145
146k = { "hello": "world" }
147k = { 'hello': 'world' }
148k = { "hello": 'world', "hat": "zat" }
149
150please "hello": "world"
151k = "hello": "world", "one": "zone"
152
153f = "one", "two": three, "four"
154f = "two": three, "four"
155f = { "one", "two": three, "four" }
156
157
158j = "one", "two": three, "four": five, 6, 7
159
160
161nil
diff --git a/spec/inputs/unless_else.moon b/spec/inputs/unless_else.moon
new file mode 100644
index 0000000..fe96c0b
--- /dev/null
+++ b/spec/inputs/unless_else.moon
@@ -0,0 +1,5 @@
1if a
2 unless b
3 print "hi"
4 elseif c
5 print "not hi"
diff --git a/spec/inputs/using.moon b/spec/inputs/using.moon
new file mode 100644
index 0000000..55a16a7
--- /dev/null
+++ b/spec/inputs/using.moon
@@ -0,0 +1,21 @@
1
2hello = "hello"
3world = "world"
4
5(using nil) ->
6 hello = 3223
7
8(a using nil) ->
9 hello = 3223
10 a = 323
11
12(a,b,c using a,b,c) ->
13 a,b,c = 1,2,3
14 world = 12321
15
16(a,e,f using a,b,c, hello) ->
17 a,b,c = 1,2,3
18 hello = 12321
19 world = "yeah"
20
21
diff --git a/spec/inputs/whitespace.moon b/spec/inputs/whitespace.moon
new file mode 100644
index 0000000..4a2ff1f
--- /dev/null
+++ b/spec/inputs/whitespace.moon
@@ -0,0 +1,102 @@
1
2{
3 1, 2
4}
5
6{ 1, 2
7}
8
9{ 1, 2 }
10
11{1,2}
12
13{
141,2
15
16}
17
18{ something 1,2,
19 4,5,6,
20 3,4,5
21}
22
23{
24 a 1,2,3,
25 4,5,6
26 1,2,3
27}
28
29
30{
31 b 1,2,3,
32 4,5,6
33 1,2,3,
34 1,2,3
35}
36
37{ 1,2,3 }
38
39{ c 1,2,3,
40}
41
42
43hello 1,2,3,4,
44 1,2,3,4,4,5
45
46x 1,
47 2, 3,
48 4, 5, 6
49
50
51hello 1,2,3,
52 world 4,5,6,
53 5,6,7,8
54
55hello 1,2,3,
56 world 4,5,6,
57 5,6,7,8,
58 9,9
59
60
61{
62 hello 1,2,
63 3,4,
64 5, 6
65}
66
67x = {
68 hello 1,2,3,4,
69 5,6,7
70 1,2,3,4
71}
72
73if hello 1,2,3,
74 world,
75 world
76 print "hello"
77
78if hello 1,2,3,
79 world,
80 world
81 print "hello"
82
83
84--
85
86a(
87 one, two, three
88)
89
90b(
91 one,
92 two,
93 three
94)
95
96
97c(one, two,
98 three, four)
99
100--
101
102nil
diff --git a/spec/inputs/with.moon b/spec/inputs/with.moon
new file mode 100644
index 0000000..ae3c8c0
--- /dev/null
+++ b/spec/inputs/with.moon
@@ -0,0 +1,118 @@
1
2do
3 a = ->
4 with something
5 print .hello
6 print hi
7 print "world"
8
9do
10 with leaf
11 .world!
12 .world 1,2,3
13
14 g = .what.is.this
15
16 .hi 1,2,3
17
18 \hi(1,2).world 2323
19
20 \hi "yeah", "man"
21 .world = 200
22
23do
24 zyzyzy = with something
25 .set_state "hello world"
26
27do
28 x = 5 + with Something!
29 \write "hello world"
30
31
32do
33 x = {
34 hello: with yeah
35 \okay!
36 }
37
38do
39 with foo
40 \prop"something".hello
41 .prop\send(one)
42 .prop\send one
43
44
45--
46
47do
48 with a, b -- b is lost
49 print .world
50
51 mod = with _M = {}
52 .Thing = "hi"
53
54 -- operate on a only
55 with a, b = something, pooh
56 print .world
57
58 x = with a, b = 1, 2
59 print a + b
60
61 print with a, b = 1, 2
62 print a + b
63
64 -- assignment lhs must be evaluated in the order they appear
65 p = with hello!.x, world!.y = 1, 2
66 print a + b
67
68--
69
70do
71 x = "hello"
72 with x
73 x\upper!
74
75do
76 with k = "jo"
77 print \upper!
78
79do
80 with a,b,c = "", "", ""
81 print \upper!
82
83do
84 a = "bunk"
85 with a,b,c = "", "", ""
86 print \upper!
87
88do
89 with j
90 print \upper!
91
92do
93 with k.j = "jo"
94 print \upper!
95
96do
97 with a
98 print .b
99 -- nested `with`s should change the scope correctly
100 with .c
101 print .d
102
103do
104 with a
105 -- nested `with`s with assignments should change the scope correctly
106 with .b = 2
107 print .c
108
109do
110 ->
111 with hi
112 return .a, .b
113
114
115do
116 with dad
117 .if "yes"
118 y = .end.of.function
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}