lua-obfuscator 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +14 -0
- package/dist/index.js +58 -0
- package/dist/prometheus/LICENSE +661 -0
- package/dist/prometheus/benchmark.lua +34 -0
- package/dist/prometheus/build.bat +10 -0
- package/dist/prometheus/cli.lua +12 -0
- package/dist/prometheus/doc/README.md +11 -0
- package/dist/prometheus/doc/SUMMARY.md +27 -0
- package/dist/prometheus/doc/advanced/using-prometheus-in-your-lua-application.md +31 -0
- package/dist/prometheus/doc/getting-started/command-line-options.md +13 -0
- package/dist/prometheus/doc/getting-started/installation.md +11 -0
- package/dist/prometheus/doc/getting-started/obfuscating-your-first-script.md +50 -0
- package/dist/prometheus/doc/getting-started/presets.md +10 -0
- package/dist/prometheus/doc/getting-started/the-config-object.md +58 -0
- package/dist/prometheus/doc/getting-started/writing-a-custom-config-file.md +56 -0
- package/dist/prometheus/doc/steps/anti-tamper.md +11 -0
- package/dist/prometheus/doc/steps/constantarray.md +71 -0
- package/dist/prometheus/doc/steps/encryptstrings.md +86 -0
- package/dist/prometheus/doc/steps/proxifylocals.md +47 -0
- package/dist/prometheus/doc/steps/splitstrings.md +40 -0
- package/dist/prometheus/doc/steps/vmify.md +9 -0
- package/dist/prometheus/doc/steps/wrapinfunction.md +29 -0
- package/dist/prometheus/prometheus-main.lua +1 -0
- package/dist/prometheus/readme.md +57 -0
- package/dist/prometheus/readme.txt +5 -0
- package/dist/prometheus/src/cli.lua +154 -0
- package/dist/prometheus/src/colors.lua +61 -0
- package/dist/prometheus/src/config.lua +35 -0
- package/dist/prometheus/src/highlightlua.lua +61 -0
- package/dist/prometheus/src/logger.lua +62 -0
- package/dist/prometheus/src/presets.lua +174 -0
- package/dist/prometheus/src/prometheus/ast.lua +792 -0
- package/dist/prometheus/src/prometheus/bit.lua +521 -0
- package/dist/prometheus/src/prometheus/compiler/compiler.lua +2365 -0
- package/dist/prometheus/src/prometheus/enums.lua +106 -0
- package/dist/prometheus/src/prometheus/namegenerators/Il.lua +41 -0
- package/dist/prometheus/src/prometheus/namegenerators/confuse.lua +169 -0
- package/dist/prometheus/src/prometheus/namegenerators/mangled.lua +26 -0
- package/dist/prometheus/src/prometheus/namegenerators/mangled_shuffled.lua +35 -0
- package/dist/prometheus/src/prometheus/namegenerators/number.lua +11 -0
- package/dist/prometheus/src/prometheus/namegenerators.lua +7 -0
- package/dist/prometheus/src/prometheus/parser.lua +969 -0
- package/dist/prometheus/src/prometheus/pipeline.lua +250 -0
- package/dist/prometheus/src/prometheus/randomLiterals.lua +41 -0
- package/dist/prometheus/src/prometheus/randomStrings.lua +24 -0
- package/dist/prometheus/src/prometheus/scope.lua +332 -0
- package/dist/prometheus/src/prometheus/step.lua +79 -0
- package/dist/prometheus/src/prometheus/steps/AddVararg.lua +33 -0
- package/dist/prometheus/src/prometheus/steps/AntiTamper.lua +194 -0
- package/dist/prometheus/src/prometheus/steps/ConstantArray.lua +521 -0
- package/dist/prometheus/src/prometheus/steps/EncryptStrings.lua +239 -0
- package/dist/prometheus/src/prometheus/steps/NumbersToExpressions.lua +82 -0
- package/dist/prometheus/src/prometheus/steps/ProxifyLocals.lua +313 -0
- package/dist/prometheus/src/prometheus/steps/SplitStrings.lua +338 -0
- package/dist/prometheus/src/prometheus/steps/Vmify.lua +30 -0
- package/dist/prometheus/src/prometheus/steps/Watermark.lua +61 -0
- package/dist/prometheus/src/prometheus/steps/WatermarkCheck.lua +50 -0
- package/dist/prometheus/src/prometheus/steps/WrapInFunction.lua +45 -0
- package/dist/prometheus/src/prometheus/steps.lua +12 -0
- package/dist/prometheus/src/prometheus/tokenizer.lua +546 -0
- package/dist/prometheus/src/prometheus/unparser.lua +866 -0
- package/dist/prometheus/src/prometheus/util.lua +297 -0
- package/dist/prometheus/src/prometheus/visitast.lua +245 -0
- package/dist/prometheus/src/prometheus.lua +71 -0
- package/dist/prometheus/tests/closures.lua +12 -0
- package/dist/prometheus/tests/fibonacci.lua +10 -0
- package/dist/prometheus/tests/loops.lua +8 -0
- package/dist/prometheus/tests/primes.lua +18 -0
- package/dist/prometheus/tests.lua +149 -0
- package/package.json +25 -0
- package/src/index.ts +76 -0
- package/src/prometheus/.editorconfig +4 -0
- package/src/prometheus/.gitattributes +2 -0
- package/src/prometheus/.gitbook.yaml +1 -0
- package/src/prometheus/.github/ISSUE_TEMPLATE/bug_report.md +25 -0
- package/src/prometheus/.github/workflows/Build.yml +49 -0
- package/src/prometheus/.github/workflows/Test.yml +19 -0
- package/src/prometheus/LICENSE +661 -0
- package/src/prometheus/benchmark.lua +34 -0
- package/src/prometheus/build.bat +10 -0
- package/src/prometheus/cli.lua +12 -0
- package/src/prometheus/doc/README.md +11 -0
- package/src/prometheus/doc/SUMMARY.md +27 -0
- package/src/prometheus/doc/advanced/using-prometheus-in-your-lua-application.md +31 -0
- package/src/prometheus/doc/getting-started/command-line-options.md +13 -0
- package/src/prometheus/doc/getting-started/installation.md +11 -0
- package/src/prometheus/doc/getting-started/obfuscating-your-first-script.md +50 -0
- package/src/prometheus/doc/getting-started/presets.md +10 -0
- package/src/prometheus/doc/getting-started/the-config-object.md +58 -0
- package/src/prometheus/doc/getting-started/writing-a-custom-config-file.md +56 -0
- package/src/prometheus/doc/steps/anti-tamper.md +11 -0
- package/src/prometheus/doc/steps/constantarray.md +71 -0
- package/src/prometheus/doc/steps/encryptstrings.md +86 -0
- package/src/prometheus/doc/steps/proxifylocals.md +47 -0
- package/src/prometheus/doc/steps/splitstrings.md +40 -0
- package/src/prometheus/doc/steps/vmify.md +9 -0
- package/src/prometheus/doc/steps/wrapinfunction.md +29 -0
- package/src/prometheus/prometheus-main.lua +1 -0
- package/src/prometheus/readme.md +57 -0
- package/src/prometheus/readme.txt +5 -0
- package/src/prometheus/src/cli.lua +154 -0
- package/src/prometheus/src/colors.lua +61 -0
- package/src/prometheus/src/highlightlua.lua +61 -0
- package/src/prometheus/src/logger.lua +62 -0
- package/src/prometheus/src/presets.lua +174 -0
- package/src/prometheus/src/prometheus/ast.lua +792 -0
- package/src/prometheus/src/prometheus/bit.lua +521 -0
- package/src/prometheus/src/prometheus/compiler/compiler.lua +2365 -0
- package/src/prometheus/src/prometheus/enums.lua +106 -0
- package/src/prometheus/src/prometheus/namegenerators/Il.lua +41 -0
- package/src/prometheus/src/prometheus/namegenerators/confuse.lua +169 -0
- package/src/prometheus/src/prometheus/namegenerators/mangled.lua +26 -0
- package/src/prometheus/src/prometheus/namegenerators/mangled_shuffled.lua +35 -0
- package/src/prometheus/src/prometheus/namegenerators/number.lua +11 -0
- package/src/prometheus/src/prometheus/namegenerators.lua +7 -0
- package/src/prometheus/src/prometheus/parser.lua +969 -0
- package/src/prometheus/src/prometheus/pipeline.lua +250 -0
- package/src/prometheus/src/prometheus/randomLiterals.lua +41 -0
- package/src/prometheus/src/prometheus/randomStrings.lua +24 -0
- package/src/prometheus/src/prometheus/scope.lua +332 -0
- package/src/prometheus/src/prometheus/step.lua +79 -0
- package/src/prometheus/src/prometheus/steps/AddVararg.lua +33 -0
- package/src/prometheus/src/prometheus/steps/AntiTamper.lua +194 -0
- package/src/prometheus/src/prometheus/steps/ConstantArray.lua +521 -0
- package/src/prometheus/src/prometheus/steps/EncryptStrings.lua +239 -0
- package/src/prometheus/src/prometheus/steps/NumbersToExpressions.lua +82 -0
- package/src/prometheus/src/prometheus/steps/ProxifyLocals.lua +313 -0
- package/src/prometheus/src/prometheus/steps/SplitStrings.lua +338 -0
- package/src/prometheus/src/prometheus/steps/Vmify.lua +30 -0
- package/src/prometheus/src/prometheus/steps/Watermark.lua +61 -0
- package/src/prometheus/src/prometheus/steps/WatermarkCheck.lua +50 -0
- package/src/prometheus/src/prometheus/steps/WrapInFunction.lua +45 -0
- package/src/prometheus/src/prometheus/steps.lua +12 -0
- package/src/prometheus/src/prometheus/tokenizer.lua +546 -0
- package/src/prometheus/src/prometheus/unparser.lua +866 -0
- package/src/prometheus/src/prometheus/util.lua +297 -0
- package/src/prometheus/src/prometheus/visitast.lua +245 -0
- package/src/prometheus/src/prometheus.lua +71 -0
- package/src/prometheus/tests/closures.lua +12 -0
- package/src/prometheus/tests/fibonacci.lua +10 -0
- package/src/prometheus/tests/loops.lua +8 -0
- package/src/prometheus/tests/primes.lua +18 -0
- package/src/prometheus/tests.lua +149 -0
- package/tsconfig.json +13 -0
|
@@ -0,0 +1,546 @@
|
|
|
1
|
+
-- This Script is Part of the Prometheus Obfuscator by Levno_710
|
|
2
|
+
--
|
|
3
|
+
-- tokenizer.lua
|
|
4
|
+
-- Overview:
|
|
5
|
+
-- This Script provides a class for lexical Analysis of lua code.
|
|
6
|
+
-- This Tokenizer is Capable of tokenizing LuaU and Lua5.1
|
|
7
|
+
local Enums = require("prometheus.enums");
|
|
8
|
+
local util = require("prometheus.util");
|
|
9
|
+
local logger = require("logger");
|
|
10
|
+
local config = require("config");
|
|
11
|
+
|
|
12
|
+
local LuaVersion = Enums.LuaVersion;
|
|
13
|
+
local lookupify = util.lookupify;
|
|
14
|
+
local unlookupify = util.unlookupify;
|
|
15
|
+
local escape = util.escape;
|
|
16
|
+
local chararray = util.chararray;
|
|
17
|
+
local keys = util.keys;
|
|
18
|
+
local Tokenizer = {};
|
|
19
|
+
|
|
20
|
+
Tokenizer.EOF_CHAR = "<EOF>";
|
|
21
|
+
Tokenizer.WHITESPACE_CHARS = lookupify{
|
|
22
|
+
" ", "\t", "\n", "\r",
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
Tokenizer.ANNOTATION_CHARS = lookupify(chararray("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_"))
|
|
26
|
+
Tokenizer.ANNOTATION_START_CHARS = lookupify(chararray("!@"))
|
|
27
|
+
|
|
28
|
+
Tokenizer.Conventions = Enums.Conventions;
|
|
29
|
+
|
|
30
|
+
Tokenizer.TokenKind = {
|
|
31
|
+
Eof = "Eof",
|
|
32
|
+
Keyword = "Keyword",
|
|
33
|
+
Symbol = "Symbol",
|
|
34
|
+
Ident = "Identifier",
|
|
35
|
+
Number = "Number",
|
|
36
|
+
String = "String",
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
Tokenizer.EOF_TOKEN = {
|
|
40
|
+
kind = Tokenizer.TokenKind.Eof,
|
|
41
|
+
value = "<EOF>",
|
|
42
|
+
startPos = -1,
|
|
43
|
+
endPos = -1,
|
|
44
|
+
source = "<EOF>",
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
local function token(self, startPos, kind, value)
|
|
48
|
+
local line, linePos = self:getPosition(self.index);
|
|
49
|
+
local annotations = self.annotations
|
|
50
|
+
self.annotations = {};
|
|
51
|
+
return {
|
|
52
|
+
kind = kind,
|
|
53
|
+
value = value,
|
|
54
|
+
startPos = startPos,
|
|
55
|
+
endPos = self.index,
|
|
56
|
+
source = self.source:sub(startPos + 1, self.index),
|
|
57
|
+
line = line,
|
|
58
|
+
linePos = linePos,
|
|
59
|
+
annotations = annotations,
|
|
60
|
+
}
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
local function generateError(self, message)
|
|
64
|
+
local line, linePos = self:getPosition(self.index);
|
|
65
|
+
return "Lexing Error at Position " .. tostring(line) .. ":" .. tostring(linePos) .. ", " .. message;
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
local function generateWarning(token, message)
|
|
69
|
+
return "Warning at Position " .. tostring(token.line) .. ":" .. tostring(token.linePos) .. ", " .. message;
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
function Tokenizer:getPosition(i)
|
|
73
|
+
local column = self.columnMap[i]
|
|
74
|
+
|
|
75
|
+
if not column then --// `i` is bigger than self.length, this shouldnt happen, but it did. (Theres probably some error in the tokenizer, cant find it.)
|
|
76
|
+
column = self.columnMap[#self.columnMap]
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
return column.id, column.charMap[i]
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
--// Prepare columnMap for getPosition
|
|
83
|
+
function Tokenizer:prepareGetPosition()
|
|
84
|
+
local columnMap, column = {}, { charMap = {}, id = 1, length = 0 }
|
|
85
|
+
|
|
86
|
+
for index = 1, self.length do
|
|
87
|
+
local character = string.sub(self.source, index, index) -- NOTE_1: this could use table.clone to reduce amount of NEWTABLE (if that causes any performance issues)
|
|
88
|
+
|
|
89
|
+
local columnLength = column.length + 1
|
|
90
|
+
column.length = columnLength
|
|
91
|
+
column.charMap[index] = columnLength
|
|
92
|
+
|
|
93
|
+
if character == "\n" then
|
|
94
|
+
column = { charMap = {}, id = column.id + 1, length = 0 } -- NOTE_1
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
columnMap[index] = column
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
self.columnMap = columnMap
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
-- Constructor for Tokenizer
|
|
104
|
+
function Tokenizer:new(settings)
|
|
105
|
+
local luaVersion = (settings and (settings.luaVersion or settings.LuaVersion)) or LuaVersion.LuaU;
|
|
106
|
+
local conventions = Tokenizer.Conventions[luaVersion];
|
|
107
|
+
|
|
108
|
+
if(conventions == nil) then
|
|
109
|
+
logger:error("The Lua Version \"" .. luaVersion .. "\" is not recognised by the Tokenizer! Please use one of the following: \"" .. table.concat(keys(Tokenizer.Conventions), "\",\"") .. "\"");
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
local tokenizer = {
|
|
113
|
+
index = 0, -- Index where the current char is read
|
|
114
|
+
length = 0,
|
|
115
|
+
source = "", -- Source to Tokenize
|
|
116
|
+
luaVersion = luaVersion, -- LuaVersion to be used while Tokenizing
|
|
117
|
+
conventions = conventions;
|
|
118
|
+
|
|
119
|
+
NumberChars = conventions.NumberChars,
|
|
120
|
+
NumberCharsLookup = lookupify(conventions.NumberChars),
|
|
121
|
+
Keywords = conventions.Keywords,
|
|
122
|
+
KeywordsLookup = lookupify(conventions.Keywords),
|
|
123
|
+
BinaryNumberChars = conventions.BinaryNumberChars,
|
|
124
|
+
BinaryNumberCharsLookup = lookupify(conventions.BinaryNumberChars);
|
|
125
|
+
BinaryNums = conventions.BinaryNums,
|
|
126
|
+
HexadecimalNums = conventions.HexadecimalNums,
|
|
127
|
+
HexNumberChars = conventions.HexNumberChars,
|
|
128
|
+
HexNumberCharsLookup = lookupify(conventions.HexNumberChars),
|
|
129
|
+
DecimalExponent = conventions.DecimalExponent,
|
|
130
|
+
DecimalSeperators = conventions.DecimalSeperators,
|
|
131
|
+
IdentChars = conventions.IdentChars,
|
|
132
|
+
IdentCharsLookup = lookupify(conventions.IdentChars),
|
|
133
|
+
|
|
134
|
+
EscapeSequences = conventions.EscapeSequences,
|
|
135
|
+
NumericalEscapes = conventions.NumericalEscapes,
|
|
136
|
+
EscapeZIgnoreNextWhitespace = conventions.EscapeZIgnoreNextWhitespace,
|
|
137
|
+
HexEscapes = conventions.HexEscapes,
|
|
138
|
+
UnicodeEscapes = conventions.UnicodeEscapes,
|
|
139
|
+
|
|
140
|
+
SymbolChars = conventions.SymbolChars,
|
|
141
|
+
SymbolCharsLookup = lookupify(conventions.SymbolChars),
|
|
142
|
+
MaxSymbolLength = conventions.MaxSymbolLength,
|
|
143
|
+
Symbols = conventions.Symbols,
|
|
144
|
+
SymbolsLookup = lookupify(conventions.Symbols),
|
|
145
|
+
|
|
146
|
+
StringStartLookup = lookupify({"\"", "\'"}),
|
|
147
|
+
annotations = {},
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
setmetatable(tokenizer, self);
|
|
151
|
+
self.__index = self;
|
|
152
|
+
|
|
153
|
+
return tokenizer;
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
-- Reset State of Tokenizer to Tokenize another File
|
|
157
|
+
function Tokenizer:reset()
|
|
158
|
+
self.index = 0;
|
|
159
|
+
self.length = 0;
|
|
160
|
+
self.source = "";
|
|
161
|
+
self.annotations = {};
|
|
162
|
+
self.columnMap = {};
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
-- Append String to this Tokenizer
|
|
166
|
+
function Tokenizer:append(code)
|
|
167
|
+
self.source = self.source .. code
|
|
168
|
+
self.length = self.length + code:len();
|
|
169
|
+
self:prepareGetPosition();
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
-- Function to peek the n'th char in the source of the tokenizer
|
|
173
|
+
local function peek(self, n)
|
|
174
|
+
n = n or 0;
|
|
175
|
+
local i = self.index + n + 1;
|
|
176
|
+
if i > self.length then
|
|
177
|
+
return Tokenizer.EOF_CHAR
|
|
178
|
+
end
|
|
179
|
+
return self.source:sub(i, i);
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
-- Function to get the next char in the source
|
|
183
|
+
local function get(self)
|
|
184
|
+
local i = self.index + 1;
|
|
185
|
+
if i > self.length then
|
|
186
|
+
logger:error(generateError(self, "Unexpected end of Input"));
|
|
187
|
+
end
|
|
188
|
+
self.index = self.index + 1;
|
|
189
|
+
return self.source:sub(i, i);
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
-- The same as get except it throws an Error if the char is not contained in charOrLookup
|
|
193
|
+
local function expect(self, charOrLookup)
|
|
194
|
+
if(type(charOrLookup) == "string") then
|
|
195
|
+
charOrLookup = {[charOrLookup] = true};
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
local char = peek(self);
|
|
199
|
+
if charOrLookup[char] ~= true then
|
|
200
|
+
local etb = unlookupify(charOrLookup);
|
|
201
|
+
for i, v in ipairs(etb) do
|
|
202
|
+
etb[i] = escape(v);
|
|
203
|
+
end
|
|
204
|
+
local errorMessage = "Unexpected char \"" .. escape(char) .. "\"! Expected one of \"" .. table.concat(etb, "\",\"") .. "\"";
|
|
205
|
+
logger:error(generateError(self, errorMessage));
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
self.index = self.index + 1;
|
|
209
|
+
return char;
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
-- Returns wether the n'th char is in the lookup
|
|
213
|
+
local function is(self, charOrLookup, n)
|
|
214
|
+
local char = peek(self, n);
|
|
215
|
+
if(type(charOrLookup) == "string") then
|
|
216
|
+
return char == charOrLookup;
|
|
217
|
+
end
|
|
218
|
+
return charOrLookup[char];
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
function Tokenizer:parseAnnotation()
|
|
222
|
+
if is(self, Tokenizer.ANNOTATION_START_CHARS) then
|
|
223
|
+
self.index = self.index + 1;
|
|
224
|
+
local source, length = {}, 0;
|
|
225
|
+
while(is(self, Tokenizer.ANNOTATION_CHARS)) do
|
|
226
|
+
source[length + 1] = get(self)
|
|
227
|
+
length = #source
|
|
228
|
+
end
|
|
229
|
+
if length > 0 then
|
|
230
|
+
self.annotations[string.lower(table.concat(source))] = true;
|
|
231
|
+
end
|
|
232
|
+
return nil;
|
|
233
|
+
end
|
|
234
|
+
return get(self);
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
-- skip one or 0 Comments and return wether one was found
|
|
238
|
+
function Tokenizer:skipComment()
|
|
239
|
+
if(is(self, "-", 0) and is(self, "-", 1)) then
|
|
240
|
+
self.index = self.index + 2;
|
|
241
|
+
if(is(self, "[")) then
|
|
242
|
+
self.index = self.index + 1;
|
|
243
|
+
local eqCount = 0;
|
|
244
|
+
while(is(self, "=")) do
|
|
245
|
+
self.index = self.index + 1;
|
|
246
|
+
eqCount = eqCount + 1;
|
|
247
|
+
end
|
|
248
|
+
if(is(self, "[")) then
|
|
249
|
+
-- Multiline Comment
|
|
250
|
+
-- Get all Chars to Closing bracket but also consider that the count of equal signs must be the same
|
|
251
|
+
while true do
|
|
252
|
+
if(self:parseAnnotation() == ']') then
|
|
253
|
+
local eqCount2 = 0;
|
|
254
|
+
while(is(self, "=")) do
|
|
255
|
+
self.index = self.index + 1;
|
|
256
|
+
eqCount2 = eqCount2 + 1;
|
|
257
|
+
end
|
|
258
|
+
if(is(self, "]")) then
|
|
259
|
+
if(eqCount2 == eqCount) then
|
|
260
|
+
self.index = self.index + 1;
|
|
261
|
+
return true
|
|
262
|
+
end
|
|
263
|
+
end
|
|
264
|
+
end
|
|
265
|
+
end
|
|
266
|
+
end
|
|
267
|
+
end
|
|
268
|
+
-- Single Line Comment
|
|
269
|
+
-- Get all Chars to next Newline
|
|
270
|
+
while(self.index < self.length and self:parseAnnotation() ~= "\n") do end
|
|
271
|
+
return true;
|
|
272
|
+
end
|
|
273
|
+
return false;
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
-- skip All Whitespace and Comments to next Token
|
|
277
|
+
function Tokenizer:skipWhitespaceAndComments()
|
|
278
|
+
while self:skipComment() do end
|
|
279
|
+
while is(self, Tokenizer.WHITESPACE_CHARS) do
|
|
280
|
+
self.index = self.index + 1;
|
|
281
|
+
while self:skipComment() do end
|
|
282
|
+
end
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
local function int(self, chars, seperators)
|
|
286
|
+
local buffer = {};
|
|
287
|
+
while true do
|
|
288
|
+
if (is(self, chars)) then
|
|
289
|
+
buffer[#buffer + 1] = get(self)
|
|
290
|
+
elseif (is(self, seperators)) then
|
|
291
|
+
self.index = self.index + 1;
|
|
292
|
+
else
|
|
293
|
+
break
|
|
294
|
+
end
|
|
295
|
+
end
|
|
296
|
+
return table.concat(buffer);
|
|
297
|
+
end
|
|
298
|
+
|
|
299
|
+
-- Lex the next token as a Number
|
|
300
|
+
function Tokenizer:number()
|
|
301
|
+
local startPos = self.index;
|
|
302
|
+
local source = expect(self, setmetatable({["."] = true}, {__index = self.NumberCharsLookup}));
|
|
303
|
+
|
|
304
|
+
if source == "0" then
|
|
305
|
+
if self.BinaryNums and is(self, lookupify(self.BinaryNums)) then
|
|
306
|
+
self.index = self.index + 1;
|
|
307
|
+
source = int(self, self.BinaryNumberCharsLookup, lookupify(self.DecimalSeperators or {}));
|
|
308
|
+
local value = tonumber(source, 2);
|
|
309
|
+
return token(self, startPos, Tokenizer.TokenKind.Number, value);
|
|
310
|
+
end
|
|
311
|
+
|
|
312
|
+
if self.HexadecimalNums and is(self, lookupify(self.HexadecimalNums)) then
|
|
313
|
+
self.index = self.index + 1;
|
|
314
|
+
source = int(self, self.HexNumberCharsLookup, lookupify(self.DecimalSeperators or {}));
|
|
315
|
+
local value = tonumber(source, 16);
|
|
316
|
+
return token(self, startPos, Tokenizer.TokenKind.Number, value);
|
|
317
|
+
end
|
|
318
|
+
end
|
|
319
|
+
|
|
320
|
+
if source == "." then
|
|
321
|
+
source = source .. int(self, self.NumberCharsLookup, lookupify(self.DecimalSeperators or {}));
|
|
322
|
+
else
|
|
323
|
+
source = source .. int(self, self.NumberCharsLookup, lookupify(self.DecimalSeperators or {}));
|
|
324
|
+
if(is(self, ".")) then
|
|
325
|
+
source = source .. get(self) .. int(self, self.NumberCharsLookup, lookupify(self.DecimalSeperators or {}));
|
|
326
|
+
end
|
|
327
|
+
end
|
|
328
|
+
|
|
329
|
+
if(self.DecimalExponent and is(self, lookupify(self.DecimalExponent))) then
|
|
330
|
+
source = source .. get(self);
|
|
331
|
+
if(is(self, lookupify({"+","-"}))) then
|
|
332
|
+
source = source .. get(self);
|
|
333
|
+
end
|
|
334
|
+
local v = int(self, self.NumberCharsLookup, lookupify(self.DecimalSeperators or {}));
|
|
335
|
+
if(v:len() < 1) then
|
|
336
|
+
logger:error(generateError(self, "Expected a Valid Exponent!"));
|
|
337
|
+
end
|
|
338
|
+
source = source .. v;
|
|
339
|
+
end
|
|
340
|
+
|
|
341
|
+
local value = tonumber(source);
|
|
342
|
+
return token(self, startPos, Tokenizer.TokenKind.Number, value);
|
|
343
|
+
end
|
|
344
|
+
|
|
345
|
+
-- Lex the Next Token as Identifier or Keyword
|
|
346
|
+
function Tokenizer:ident()
|
|
347
|
+
local startPos = self.index;
|
|
348
|
+
local source = expect(self, self.IdentCharsLookup)
|
|
349
|
+
local sourceAddContent = {source}
|
|
350
|
+
while(is(self, self.IdentCharsLookup)) do
|
|
351
|
+
-- source = source .. get(self);
|
|
352
|
+
table.insert(sourceAddContent, get(self))
|
|
353
|
+
end
|
|
354
|
+
source = table.concat(sourceAddContent)
|
|
355
|
+
if(self.KeywordsLookup[source]) then
|
|
356
|
+
return token(self, startPos, Tokenizer.TokenKind.Keyword, source);
|
|
357
|
+
end
|
|
358
|
+
|
|
359
|
+
local tk = token(self, startPos, Tokenizer.TokenKind.Ident, source);
|
|
360
|
+
|
|
361
|
+
if(string.sub(source, 1, string.len(config.IdentPrefix)) == config.IdentPrefix) then
|
|
362
|
+
logger:warn(generateWarning(tk, string.format("identifiers should not start with \"%s\" as this may break the program", config.IdentPrefix)));
|
|
363
|
+
end
|
|
364
|
+
|
|
365
|
+
return tk;
|
|
366
|
+
end
|
|
367
|
+
|
|
368
|
+
function Tokenizer:singleLineString()
|
|
369
|
+
local startPos = self.index;
|
|
370
|
+
local startChar = expect(self, self.StringStartLookup);
|
|
371
|
+
local buffer = {};
|
|
372
|
+
|
|
373
|
+
while (not is(self, startChar)) do
|
|
374
|
+
local char = get(self);
|
|
375
|
+
|
|
376
|
+
-- Single Line String may not contain Linebreaks except when they are escaped by \
|
|
377
|
+
if(char == '\n') then
|
|
378
|
+
self.index = self.index - 1;
|
|
379
|
+
logger:error(generateError(self, "Unterminated String"));
|
|
380
|
+
end
|
|
381
|
+
|
|
382
|
+
|
|
383
|
+
if(char == "\\") then
|
|
384
|
+
char = get(self);
|
|
385
|
+
|
|
386
|
+
local escape = self.EscapeSequences[char];
|
|
387
|
+
if(type(escape) == "string") then
|
|
388
|
+
char = escape;
|
|
389
|
+
|
|
390
|
+
elseif(self.NumericalEscapes and self.NumberCharsLookup[char]) then
|
|
391
|
+
local numstr = char;
|
|
392
|
+
|
|
393
|
+
if(is(self, self.NumberCharsLookup)) then
|
|
394
|
+
char = get(self);
|
|
395
|
+
numstr = numstr .. char;
|
|
396
|
+
end
|
|
397
|
+
|
|
398
|
+
if(is(self, self.NumberCharsLookup)) then
|
|
399
|
+
char = get(self);
|
|
400
|
+
numstr = numstr .. char;
|
|
401
|
+
end
|
|
402
|
+
|
|
403
|
+
char = string.char(tonumber(numstr));
|
|
404
|
+
|
|
405
|
+
elseif(self.UnicodeEscapes and char == "u") then
|
|
406
|
+
expect(self, "{");
|
|
407
|
+
local num = "";
|
|
408
|
+
while (is(self, self.HexNumberCharsLookup)) do
|
|
409
|
+
num = num .. get(self);
|
|
410
|
+
end
|
|
411
|
+
expect(self, "}");
|
|
412
|
+
char = util.utf8char(tonumber(num, 16));
|
|
413
|
+
elseif(self.HexEscapes and char == "x") then
|
|
414
|
+
local hex = expect(self, self.HexNumberCharsLookup) .. expect(self, self.HexNumberCharsLookup);
|
|
415
|
+
char = string.char(tonumber(hex, 16));
|
|
416
|
+
elseif(self.EscapeZIgnoreNextWhitespace and char == "z") then
|
|
417
|
+
char = "";
|
|
418
|
+
while(is(self, Tokenizer.WHITESPACE_CHARS)) do
|
|
419
|
+
self.index = self.index + 1;
|
|
420
|
+
end
|
|
421
|
+
end
|
|
422
|
+
end
|
|
423
|
+
|
|
424
|
+
--// since table.insert is slower in lua51
|
|
425
|
+
buffer[#buffer + 1] = char
|
|
426
|
+
end
|
|
427
|
+
|
|
428
|
+
expect(self, startChar);
|
|
429
|
+
|
|
430
|
+
return token(self, startPos, Tokenizer.TokenKind.String, table.concat(buffer))
|
|
431
|
+
end
|
|
432
|
+
|
|
433
|
+
function Tokenizer:multiLineString()
|
|
434
|
+
local startPos = self.index;
|
|
435
|
+
if(is(self, "[")) then
|
|
436
|
+
self.index = self.index + 1;
|
|
437
|
+
local eqCount = 0;
|
|
438
|
+
while(is(self, "=")) do
|
|
439
|
+
self.index = self.index + 1;
|
|
440
|
+
eqCount = eqCount + 1;
|
|
441
|
+
end
|
|
442
|
+
if(is(self, "[")) then
|
|
443
|
+
-- Multiline String
|
|
444
|
+
-- Parse String to Closing bracket but also consider that the count of equal signs must be the same
|
|
445
|
+
|
|
446
|
+
-- Skip Leading newline if existing
|
|
447
|
+
self.index = self.index + 1;
|
|
448
|
+
if(is(self, "\n")) then
|
|
449
|
+
self.index = self.index + 1;
|
|
450
|
+
end
|
|
451
|
+
|
|
452
|
+
local value = "";
|
|
453
|
+
while true do
|
|
454
|
+
local char = get(self);
|
|
455
|
+
if(char == ']') then
|
|
456
|
+
local eqCount2 = 0;
|
|
457
|
+
while(is(self, "=")) do
|
|
458
|
+
char = char .. get(self);
|
|
459
|
+
eqCount2 = eqCount2 + 1;
|
|
460
|
+
end
|
|
461
|
+
if(is(self, "]")) then
|
|
462
|
+
if(eqCount2 == eqCount) then
|
|
463
|
+
self.index = self.index + 1;
|
|
464
|
+
return token(self, startPos, Tokenizer.TokenKind.String, value), true
|
|
465
|
+
end
|
|
466
|
+
end
|
|
467
|
+
end
|
|
468
|
+
value = value .. char;
|
|
469
|
+
end
|
|
470
|
+
end
|
|
471
|
+
end
|
|
472
|
+
self.index = startPos;
|
|
473
|
+
return nil, false -- There was not an actual multiline string at the given Position
|
|
474
|
+
end
|
|
475
|
+
|
|
476
|
+
function Tokenizer:symbol()
|
|
477
|
+
local startPos = self.index;
|
|
478
|
+
for len = self.MaxSymbolLength, 1, -1 do
|
|
479
|
+
local str = self.source:sub(self.index + 1, self.index + len);
|
|
480
|
+
if self.SymbolsLookup[str] then
|
|
481
|
+
self.index = self.index + len;
|
|
482
|
+
return token(self, startPos, Tokenizer.TokenKind.Symbol, str);
|
|
483
|
+
end
|
|
484
|
+
end
|
|
485
|
+
logger:error(generateError(self, "Unknown Symbol"));
|
|
486
|
+
end
|
|
487
|
+
|
|
488
|
+
|
|
489
|
+
-- get the Next token
|
|
490
|
+
function Tokenizer:next()
|
|
491
|
+
-- Skip All Whitespace before the token
|
|
492
|
+
self:skipWhitespaceAndComments();
|
|
493
|
+
|
|
494
|
+
local startPos = self.index;
|
|
495
|
+
if startPos >= self.length then
|
|
496
|
+
return token(self, startPos, Tokenizer.TokenKind.Eof);
|
|
497
|
+
end
|
|
498
|
+
|
|
499
|
+
-- Numbers
|
|
500
|
+
if(is(self, self.NumberCharsLookup)) then
|
|
501
|
+
return self:number();
|
|
502
|
+
end
|
|
503
|
+
|
|
504
|
+
-- Identifiers and Keywords
|
|
505
|
+
if(is(self, self.IdentCharsLookup)) then
|
|
506
|
+
return self:ident();
|
|
507
|
+
end
|
|
508
|
+
|
|
509
|
+
-- Singleline String Literals
|
|
510
|
+
if(is(self, self.StringStartLookup)) then
|
|
511
|
+
return self:singleLineString();
|
|
512
|
+
end
|
|
513
|
+
|
|
514
|
+
-- Multiline String Literals
|
|
515
|
+
if(is(self, "[", 0)) then
|
|
516
|
+
-- The isString variable is due to the fact that "[" could also be a symbol for indexing
|
|
517
|
+
local value, isString = self:multiLineString();
|
|
518
|
+
if isString then
|
|
519
|
+
return value;
|
|
520
|
+
end
|
|
521
|
+
end
|
|
522
|
+
|
|
523
|
+
-- Number starting with dot
|
|
524
|
+
if(is(self, ".") and is(self, self.NumberCharsLookup, 1)) then
|
|
525
|
+
return self:number();
|
|
526
|
+
end
|
|
527
|
+
|
|
528
|
+
-- Symbols
|
|
529
|
+
if(is(self, self.SymbolCharsLookup)) then
|
|
530
|
+
return self:symbol();
|
|
531
|
+
end
|
|
532
|
+
|
|
533
|
+
|
|
534
|
+
logger:error(generateError(self, "Unexpected char \"" .. escape(peek(self)) .. "\"!"));
|
|
535
|
+
end
|
|
536
|
+
|
|
537
|
+
function Tokenizer:scanAll()
|
|
538
|
+
local tb = {};
|
|
539
|
+
repeat
|
|
540
|
+
local token = self:next();
|
|
541
|
+
table.insert(tb, token);
|
|
542
|
+
until token.kind == Tokenizer.TokenKind.Eof
|
|
543
|
+
return tb
|
|
544
|
+
end
|
|
545
|
+
|
|
546
|
+
return Tokenizer
|