mevento 2.0.5 → 2.1.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/esm2020/lib/mevento.mjs +140 -41
- package/fesm2015/mevento.mjs +141 -41
- package/fesm2015/mevento.mjs.map +1 -1
- package/fesm2020/mevento.mjs +139 -40
- package/fesm2020/mevento.mjs.map +1 -1
- package/lib/mevento.d.ts +1 -2
- package/package.json +1 -1
package/fesm2020/mevento.mjs
CHANGED
|
@@ -178,6 +178,15 @@ class Lexer {
|
|
|
178
178
|
this._currentChar = this._source[this._position].charCodeAt(0);
|
|
179
179
|
this._col++;
|
|
180
180
|
}
|
|
181
|
+
_jump(n) {
|
|
182
|
+
this._position += n;
|
|
183
|
+
if (this._position >= this._source.length) {
|
|
184
|
+
this._currentChar = -1;
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
this._currentChar = this._source[this._position].charCodeAt(0);
|
|
188
|
+
this._col += n;
|
|
189
|
+
}
|
|
181
190
|
_pick() {
|
|
182
191
|
if (this._position + 1 >= this._source.length) {
|
|
183
192
|
return -1;
|
|
@@ -311,28 +320,62 @@ class Lexer {
|
|
|
311
320
|
const lastL = this._line;
|
|
312
321
|
while (this._currentChar !== -1) {
|
|
313
322
|
const next = String.fromCharCode(this._pick());
|
|
314
|
-
if (this._currentChar
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
'0'
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
'
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
'
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
'
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
323
|
+
if (this._currentChar == Chars.backslash) {
|
|
324
|
+
switch (next) {
|
|
325
|
+
case '\\':
|
|
326
|
+
ret += "\\";
|
|
327
|
+
break;
|
|
328
|
+
case '0':
|
|
329
|
+
ret += "\0";
|
|
330
|
+
break;
|
|
331
|
+
case 'a':
|
|
332
|
+
ret += "\a";
|
|
333
|
+
break;
|
|
334
|
+
case 'b':
|
|
335
|
+
ret += "\b";
|
|
336
|
+
break;
|
|
337
|
+
case 'f':
|
|
338
|
+
ret += "\f";
|
|
339
|
+
break;
|
|
340
|
+
case 'n':
|
|
341
|
+
ret += "\n";
|
|
342
|
+
break;
|
|
343
|
+
case 'r':
|
|
344
|
+
ret += "\r";
|
|
345
|
+
break;
|
|
346
|
+
case 't':
|
|
347
|
+
ret += "\t";
|
|
348
|
+
break;
|
|
349
|
+
case 'u':
|
|
350
|
+
ret += String.fromCharCode(Number.parseInt(this._source.substring(this._position + 2, this._position + 6), 16));
|
|
351
|
+
this._jump(4);
|
|
352
|
+
// consume 4 unicode chars
|
|
353
|
+
break;
|
|
354
|
+
case 'v':
|
|
355
|
+
ret += "\v";
|
|
356
|
+
break;
|
|
357
|
+
case 'x':
|
|
358
|
+
ret += String.fromCharCode(Number.parseInt(this._source.substring(this._position + 2, this._position + 4), 16));
|
|
359
|
+
this._jump(2);
|
|
360
|
+
break;
|
|
361
|
+
default:
|
|
362
|
+
{
|
|
363
|
+
if (String.fromCharCode(startChar) == next) {
|
|
364
|
+
ret += String.fromCharCode(startChar);
|
|
365
|
+
}
|
|
366
|
+
else {
|
|
367
|
+
this._advance();
|
|
368
|
+
lastChar = this._currentChar;
|
|
369
|
+
ret += String.fromCharCode(this._currentChar);
|
|
370
|
+
this._advance();
|
|
371
|
+
continue;
|
|
372
|
+
}
|
|
373
|
+
}
|
|
335
374
|
}
|
|
375
|
+
// scape char
|
|
376
|
+
this._jump(2);
|
|
377
|
+
lastChar = this._currentChar;
|
|
378
|
+
continue;
|
|
336
379
|
}
|
|
337
380
|
if (this._currentChar === startChar && lastChar !== Chars.backslash) {
|
|
338
381
|
// end
|
|
@@ -798,8 +841,33 @@ class ContinueAST extends AST {
|
|
|
798
841
|
super(line, col);
|
|
799
842
|
}
|
|
800
843
|
}
|
|
844
|
+
class ListQueue {
|
|
845
|
+
constructor(capacity = Infinity) {
|
|
846
|
+
this.capacity = capacity;
|
|
847
|
+
this.storage = [];
|
|
848
|
+
}
|
|
849
|
+
push(item) {
|
|
850
|
+
if (this.size() === this.capacity) {
|
|
851
|
+
throw Error("Stack has reached max capacity, you cannot add more items");
|
|
852
|
+
}
|
|
853
|
+
this.storage.push(item);
|
|
854
|
+
}
|
|
855
|
+
pop() {
|
|
856
|
+
return this.storage.pop();
|
|
857
|
+
}
|
|
858
|
+
peek() {
|
|
859
|
+
return this.storage[this.size() - 1];
|
|
860
|
+
}
|
|
861
|
+
size() {
|
|
862
|
+
return this.storage.length;
|
|
863
|
+
}
|
|
864
|
+
get isEmpty() {
|
|
865
|
+
return this.storage.length === 0;
|
|
866
|
+
}
|
|
867
|
+
}
|
|
801
868
|
class Parser {
|
|
802
869
|
constructor(lexer) {
|
|
870
|
+
this._loopTrack = new ListQueue();
|
|
803
871
|
this.currentToken = lexer.nextToken();
|
|
804
872
|
this.lexer = lexer;
|
|
805
873
|
}
|
|
@@ -873,10 +941,32 @@ class Parser {
|
|
|
873
941
|
return this._objectExpression();
|
|
874
942
|
case TokenType.IF:
|
|
875
943
|
return this._ifStatement();
|
|
944
|
+
case TokenType.WHILE_TILL:
|
|
945
|
+
return this._whileLoop(true);
|
|
946
|
+
case TokenType.FOR_LOOP:
|
|
947
|
+
return this._forLoop(true);
|
|
948
|
+
case TokenType.BREAK:
|
|
949
|
+
return this._breakExpression();
|
|
950
|
+
case TokenType.CONTINUE:
|
|
951
|
+
return this._continueExpression();
|
|
876
952
|
default:
|
|
877
953
|
return this._variable();
|
|
878
954
|
}
|
|
879
955
|
}
|
|
956
|
+
_breakExpression() {
|
|
957
|
+
if (this._loopTrack.isEmpty) {
|
|
958
|
+
error(this.currentToken);
|
|
959
|
+
}
|
|
960
|
+
this._eat(TokenType.BREAK);
|
|
961
|
+
return new BreakAST(this.currentToken?.line, this.currentToken?.col);
|
|
962
|
+
}
|
|
963
|
+
_continueExpression() {
|
|
964
|
+
if (this._loopTrack.isEmpty) {
|
|
965
|
+
error(this.currentToken);
|
|
966
|
+
}
|
|
967
|
+
this._eat(TokenType.CONTINUE);
|
|
968
|
+
return new ContinueAST(this.currentToken?.line, this.currentToken?.col);
|
|
969
|
+
}
|
|
880
970
|
_term() {
|
|
881
971
|
let node = this._factor();
|
|
882
972
|
node = this._tryParsingFunctionCall(node);
|
|
@@ -1111,12 +1201,20 @@ class Parser {
|
|
|
1111
1201
|
}
|
|
1112
1202
|
return new IfStatementAST(test, consequent, alternate);
|
|
1113
1203
|
}
|
|
1114
|
-
|
|
1204
|
+
_pushLoop() {
|
|
1205
|
+
this._loopTrack.push(true);
|
|
1206
|
+
}
|
|
1207
|
+
_popLoop() {
|
|
1208
|
+
this._loopTrack.pop();
|
|
1209
|
+
}
|
|
1210
|
+
_whileLoop(retain = false) {
|
|
1115
1211
|
const token = this.currentToken;
|
|
1116
1212
|
this._eat(TokenType.WHILE_TILL);
|
|
1213
|
+
this._pushLoop();
|
|
1117
1214
|
const test = this._expression();
|
|
1118
1215
|
const body = this.currentToken.type === TokenType.lbrace ? this._blockStatement() : this._expression();
|
|
1119
|
-
|
|
1216
|
+
this._popLoop();
|
|
1217
|
+
return new WhileLoopStatement(test, body, token, this.currentToken, retain);
|
|
1120
1218
|
}
|
|
1121
1219
|
_forOfIdentifier() {
|
|
1122
1220
|
switch (this.currentToken.type) {
|
|
@@ -1142,9 +1240,10 @@ class Parser {
|
|
|
1142
1240
|
* }
|
|
1143
1241
|
* (seginka|for) mali kono a
|
|
1144
1242
|
*/
|
|
1145
|
-
_forLoop() {
|
|
1243
|
+
_forLoop(retain = false) {
|
|
1146
1244
|
const startToken = this.currentToken;
|
|
1147
1245
|
this._eat(TokenType.FOR_LOOP);
|
|
1246
|
+
this._pushLoop();
|
|
1148
1247
|
let forOf = [TokenType.lparen].includes(this.currentToken.type);
|
|
1149
1248
|
let node;
|
|
1150
1249
|
if (forOf) {
|
|
@@ -1180,13 +1279,15 @@ class Parser {
|
|
|
1180
1279
|
update = new LiteralAST(new Token(TokenType.numberConst, 1, this.currentToken.line, this.currentToken.col), "1");
|
|
1181
1280
|
}
|
|
1182
1281
|
const body = (this.currentToken.type === TokenType.lbrace) ? this._blockStatement() : this._expression();
|
|
1183
|
-
node = new ForLoopStatement(node, test, update, direction, body, startToken, this.currentToken);
|
|
1282
|
+
node = new ForLoopStatement(node, test, update, direction, body, startToken, this.currentToken, retain);
|
|
1283
|
+
this._popLoop();
|
|
1184
1284
|
}
|
|
1185
1285
|
else if (forOf) {
|
|
1186
1286
|
this._eat(TokenType.in);
|
|
1187
1287
|
const collection = this._expression();
|
|
1188
1288
|
const body = (this.currentToken.type === TokenType.lbrace) ? this._blockStatement() : this._expression();
|
|
1189
|
-
node = new ForOfStatement(node, collection, body, startToken, this.currentToken);
|
|
1289
|
+
node = new ForOfStatement(node, collection, body, startToken, this.currentToken, retain);
|
|
1290
|
+
this._popLoop();
|
|
1190
1291
|
}
|
|
1191
1292
|
else {
|
|
1192
1293
|
error(this.currentToken);
|
|
@@ -1196,11 +1297,9 @@ class Parser {
|
|
|
1196
1297
|
_statement() {
|
|
1197
1298
|
switch (this.currentToken.type) {
|
|
1198
1299
|
case TokenType.BREAK:
|
|
1199
|
-
this.
|
|
1200
|
-
return new BreakAST(this.currentToken?.line, this.currentToken?.col);
|
|
1300
|
+
return this._breakExpression();
|
|
1201
1301
|
case TokenType.CONTINUE:
|
|
1202
|
-
this.
|
|
1203
|
-
return new ContinueAST(this.currentToken?.line, this.currentToken?.col);
|
|
1302
|
+
return this._continueExpression();
|
|
1204
1303
|
case TokenType.RETURN:
|
|
1205
1304
|
this._eat(TokenType.RETURN);
|
|
1206
1305
|
return this._return();
|
|
@@ -1477,17 +1576,17 @@ class MEvento extends NodeVisitor {
|
|
|
1477
1576
|
if (isNum(lValue) && isNum(rValue)) {
|
|
1478
1577
|
return lValue - rValue;
|
|
1479
1578
|
}
|
|
1480
|
-
if (isString(lValue) && isNum(rValue)) {
|
|
1481
|
-
return lValue * rValue;
|
|
1482
|
-
}
|
|
1483
|
-
if (isNum(lValue) && isString(rValue)) {
|
|
1484
|
-
return rValue * lValue;
|
|
1485
|
-
}
|
|
1486
1579
|
throw new Error(`Operation ${op.value} not allowed no num value`);
|
|
1487
1580
|
case TokenType.mult:
|
|
1488
1581
|
if (isNum(lValue) && isNum(rValue)) {
|
|
1489
1582
|
return lValue * rValue;
|
|
1490
1583
|
}
|
|
1584
|
+
if (isString(lValue) && isNum(rValue)) {
|
|
1585
|
+
return lValue.repeat(rValue);
|
|
1586
|
+
}
|
|
1587
|
+
if (isNum(lValue) && isString(rValue)) {
|
|
1588
|
+
return rValue.repeat(lValue);
|
|
1589
|
+
}
|
|
1491
1590
|
throw new Error(`Operation ${op.value} not allowed no num value`);
|
|
1492
1591
|
case TokenType.div:
|
|
1493
1592
|
if (isNum(lValue) && isNum(rValue)) {
|
|
@@ -1648,7 +1747,7 @@ class MEvento extends NodeVisitor {
|
|
|
1648
1747
|
this.pushScope("ForLoopStatement");
|
|
1649
1748
|
const initialValue = this.visit(node.init.init);
|
|
1650
1749
|
this.changeVariable(loopIdentifier.value, initialValue);
|
|
1651
|
-
retainer?.push(initialValue)
|
|
1750
|
+
// retainer?.push(initialValue)
|
|
1652
1751
|
const test = () => {
|
|
1653
1752
|
const ret = this.visit(node.test);
|
|
1654
1753
|
if (isNum(ret)) {
|
|
@@ -1889,10 +1988,10 @@ class MEventoAsync extends MEvento {
|
|
|
1889
1988
|
return lValue - rValue;
|
|
1890
1989
|
}
|
|
1891
1990
|
if (isString(lValue) && isNum(rValue)) {
|
|
1892
|
-
return lValue
|
|
1991
|
+
return lValue.repeat(rValue);
|
|
1893
1992
|
}
|
|
1894
1993
|
if (isNum(lValue) && isString(rValue)) {
|
|
1895
|
-
return rValue
|
|
1994
|
+
return rValue.repeat(lValue);
|
|
1896
1995
|
}
|
|
1897
1996
|
throw new Error(`Operation ${op.value} not allowed no num value`);
|
|
1898
1997
|
case TokenType.mult:
|
|
@@ -2056,7 +2155,7 @@ class MEventoAsync extends MEvento {
|
|
|
2056
2155
|
this.pushScope("ForLoopStatement");
|
|
2057
2156
|
const initialValue = await this.visit(node.init.init);
|
|
2058
2157
|
this.changeVariable(loopIdentifier.value, initialValue);
|
|
2059
|
-
retainer?.push(initialValue)
|
|
2158
|
+
// retainer?.push(initialValue)
|
|
2060
2159
|
const test = async () => {
|
|
2061
2160
|
const ret = await this.visit(node.test);
|
|
2062
2161
|
if (isNum(ret)) {
|