bare-script 3.3.2 → 3.5.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/lib/model.js +18 -0
- package/lib/parser.js +45 -39
- package/lib/runtime.js +36 -4
- package/lib/runtimeAsync.js +36 -4
- package/package.json +2 -2
package/lib/model.js
CHANGED
|
@@ -162,6 +162,12 @@ enum BinaryExpressionOperator
|
|
|
162
162
|
# Subtraction
|
|
163
163
|
"-"
|
|
164
164
|
|
|
165
|
+
# Bitwise left shift
|
|
166
|
+
"<<"
|
|
167
|
+
|
|
168
|
+
# Bitwise right shift
|
|
169
|
+
">>"
|
|
170
|
+
|
|
165
171
|
# Less than or equal
|
|
166
172
|
"<="
|
|
167
173
|
|
|
@@ -180,6 +186,15 @@ enum BinaryExpressionOperator
|
|
|
180
186
|
# Not equal
|
|
181
187
|
"!="
|
|
182
188
|
|
|
189
|
+
# Bitwise AND
|
|
190
|
+
"&"
|
|
191
|
+
|
|
192
|
+
# Bitwise XOR
|
|
193
|
+
"^"
|
|
194
|
+
|
|
195
|
+
# Bitwise OR
|
|
196
|
+
"|"
|
|
197
|
+
|
|
183
198
|
# Logical AND
|
|
184
199
|
"&&"
|
|
185
200
|
|
|
@@ -206,6 +221,9 @@ enum UnaryExpressionOperator
|
|
|
206
221
|
# Logical NOT
|
|
207
222
|
"!"
|
|
208
223
|
|
|
224
|
+
# Bitwise NOT
|
|
225
|
+
"~"
|
|
226
|
+
|
|
209
227
|
|
|
210
228
|
# A function expression
|
|
211
229
|
struct FunctionExpression
|
package/lib/parser.js
CHANGED
|
@@ -539,18 +539,23 @@ function parseBinaryExpression(exprText, binLeftExpr = null) {
|
|
|
539
539
|
|
|
540
540
|
// Binary operator re-order map
|
|
541
541
|
const binaryReorder = {
|
|
542
|
-
'**': new Set(['*', '/', '%', '+', '-', '<=', '<', '>=', '>', '==', '!=', '&&', '||']),
|
|
543
|
-
'*': new Set(['+', '-', '<=', '<', '>=', '>', '==', '!=', '&&', '||']),
|
|
544
|
-
'/': new Set(['+', '-', '<=', '<', '>=', '>', '==', '!=', '&&', '||']),
|
|
545
|
-
'%': new Set(['+', '-', '<=', '<', '>=', '>', '==', '!=', '&&', '||']),
|
|
546
|
-
'+': new Set(['<=', '<', '>=', '>', '==', '!=', '&&', '||']),
|
|
547
|
-
'-': new Set(['<=', '<', '>=', '>', '==', '!=', '&&', '||']),
|
|
548
|
-
'
|
|
549
|
-
'
|
|
550
|
-
'
|
|
551
|
-
'
|
|
552
|
-
'
|
|
553
|
-
'
|
|
542
|
+
'**': new Set(['*', '/', '%', '+', '-', '<<', '>>', '<=', '<', '>=', '>', '==', '!=', '&', '^', '|', '&&', '||']),
|
|
543
|
+
'*': new Set(['+', '-', '<<', '>>', '<=', '<', '>=', '>', '==', '!=', '&', '^', '|', '&&', '||']),
|
|
544
|
+
'/': new Set(['+', '-', '<<', '>>', '<=', '<', '>=', '>', '==', '!=', '&', '^', '|', '&&', '||']),
|
|
545
|
+
'%': new Set(['+', '-', '<<', '>>', '<=', '<', '>=', '>', '==', '!=', '&', '^', '|', '&&', '||']),
|
|
546
|
+
'+': new Set(['<<', '>>', '<=', '<', '>=', '>', '==', '!=', '&', '^', '|', '&&', '||']),
|
|
547
|
+
'-': new Set(['<<', '>>', '<=', '<', '>=', '>', '==', '!=', '&', '^', '|', '&&', '||']),
|
|
548
|
+
'<<': new Set(['<=', '<', '>=', '>', '==', '!=', '&', '^', '|', '&&', '||']),
|
|
549
|
+
'>>': new Set(['<=', '<', '>=', '>', '==', '!=', '&', '^', '|', '&&', '||']),
|
|
550
|
+
'<=': new Set(['==', '!=', '&', '^', '|', '&&', '||']),
|
|
551
|
+
'<': new Set(['==', '!=', '&', '^', '|', '&&', '||']),
|
|
552
|
+
'>=': new Set(['==', '!=', '&', '^', '|', '&&', '||']),
|
|
553
|
+
'>': new Set(['==', '!=', '&', '^', '|', '&&', '||']),
|
|
554
|
+
'==': new Set(['&', '^', '|', '&&', '||']),
|
|
555
|
+
'!=': new Set(['&', '^', '|', '&&', '||']),
|
|
556
|
+
'&': new Set(['^', '|', '&&', '||']),
|
|
557
|
+
'^': new Set(['|', '&&', '||']),
|
|
558
|
+
'|': new Set(['&&', '||']),
|
|
554
559
|
'&&': new Set(['||']),
|
|
555
560
|
'||': new Set([])
|
|
556
561
|
};
|
|
@@ -570,6 +575,31 @@ function parseUnaryExpression(exprText) {
|
|
|
570
575
|
return [{'group': expr}, nextText.slice(matchGroupClose[0].length)];
|
|
571
576
|
}
|
|
572
577
|
|
|
578
|
+
// Number?
|
|
579
|
+
const matchNumber = exprText.match(rExprNumber);
|
|
580
|
+
if (matchNumber !== null) {
|
|
581
|
+
const [numberStr] = matchNumber;
|
|
582
|
+
const number = (numberStr.startsWith('0x') ? parseInt(numberStr, 16) : parseFloat(numberStr));
|
|
583
|
+
const expr = {'number': number};
|
|
584
|
+
return [expr, exprText.slice(matchNumber[0].length)];
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
// String?
|
|
588
|
+
const matchString = exprText.match(rExprString);
|
|
589
|
+
if (matchString !== null) {
|
|
590
|
+
const string = matchString[1].replace(rExprStringEscape, '$1');
|
|
591
|
+
const expr = {'string': string};
|
|
592
|
+
return [expr, exprText.slice(matchString[0].length)];
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
// String (double quotes)?
|
|
596
|
+
const matchStringDouble = exprText.match(rExprStringDouble);
|
|
597
|
+
if (matchStringDouble !== null) {
|
|
598
|
+
const string = matchStringDouble[1].replace(rExprStringDoubleEscape, '$1');
|
|
599
|
+
const expr = {'string': string};
|
|
600
|
+
return [expr, exprText.slice(matchStringDouble[0].length)];
|
|
601
|
+
}
|
|
602
|
+
|
|
573
603
|
// Unary operator?
|
|
574
604
|
const matchUnary = exprText.match(rExprUnaryOp);
|
|
575
605
|
if (matchUnary !== null) {
|
|
@@ -621,30 +651,6 @@ function parseUnaryExpression(exprText) {
|
|
|
621
651
|
return [fnExpr, argText];
|
|
622
652
|
}
|
|
623
653
|
|
|
624
|
-
// Number?
|
|
625
|
-
const matchNumber = exprText.match(rExprNumber);
|
|
626
|
-
if (matchNumber !== null) {
|
|
627
|
-
const number = parseFloat(matchNumber[1]);
|
|
628
|
-
const expr = {'number': number};
|
|
629
|
-
return [expr, exprText.slice(matchNumber[0].length)];
|
|
630
|
-
}
|
|
631
|
-
|
|
632
|
-
// String?
|
|
633
|
-
const matchString = exprText.match(rExprString);
|
|
634
|
-
if (matchString !== null) {
|
|
635
|
-
const string = matchString[1].replace(rExprStringEscape, '$1');
|
|
636
|
-
const expr = {'string': string};
|
|
637
|
-
return [expr, exprText.slice(matchString[0].length)];
|
|
638
|
-
}
|
|
639
|
-
|
|
640
|
-
// String (double quotes)?
|
|
641
|
-
const matchStringDouble = exprText.match(rExprStringDouble);
|
|
642
|
-
if (matchStringDouble !== null) {
|
|
643
|
-
const string = matchStringDouble[1].replace(rExprStringDoubleEscape, '$1');
|
|
644
|
-
const expr = {'string': string};
|
|
645
|
-
return [expr, exprText.slice(matchStringDouble[0].length)];
|
|
646
|
-
}
|
|
647
|
-
|
|
648
654
|
// Variable?
|
|
649
655
|
const matchVariable = exprText.match(rExprVariable);
|
|
650
656
|
if (matchVariable !== null) {
|
|
@@ -665,14 +671,14 @@ function parseUnaryExpression(exprText) {
|
|
|
665
671
|
|
|
666
672
|
|
|
667
673
|
// BareScript expression regex
|
|
668
|
-
const rExprBinaryOp = /^\s*(
|
|
669
|
-
const rExprUnaryOp = /^\s*(
|
|
674
|
+
const rExprBinaryOp = /^\s*(\*\*|\*|\/|%|\+|-|<<|>>|<=|<|>=|>|==|!=|&&|\|\||&|\^|\|)/;
|
|
675
|
+
const rExprUnaryOp = /^\s*(!|-|~)/;
|
|
670
676
|
const rExprFunctionOpen = /^\s*([A-Za-z_]\w+)\s*\(/;
|
|
671
677
|
const rExprFunctionSeparator = /^\s*,/;
|
|
672
678
|
const rExprFunctionClose = /^\s*\)/;
|
|
673
679
|
const rExprGroupOpen = /^\s*\(/;
|
|
674
680
|
const rExprGroupClose = /^\s*\)/;
|
|
675
|
-
const rExprNumber = /^\s*([+-]?\d+(?:\.\d*)?(?:e[+-]
|
|
681
|
+
const rExprNumber = /^\s*(0x[A-Fa-f0-9]+|[+-]?\d+(?:\.\d*)?(?:e[+-]?\d+)?)/;
|
|
676
682
|
const rExprString = /^\s*'((?:\\\\|\\'|[^'])*)'/;
|
|
677
683
|
const rExprStringEscape = /\\([\\'])/g;
|
|
678
684
|
const rExprStringDouble = /^\s*"((?:\\\\|\\"|[^"])*)"/;
|
package/lib/runtime.js
CHANGED
|
@@ -300,12 +300,37 @@ export function evaluateExpression(expr, options = null, locals = null, builtins
|
|
|
300
300
|
if (typeof leftValue === 'number' && typeof rightValue === 'number') {
|
|
301
301
|
return leftValue % rightValue;
|
|
302
302
|
}
|
|
303
|
-
} else {
|
|
304
|
-
// binOp === '**'
|
|
303
|
+
} else if (binOp === '**') {
|
|
305
304
|
// number ** number
|
|
306
305
|
if (typeof leftValue === 'number' && typeof rightValue === 'number') {
|
|
307
306
|
return leftValue ** rightValue;
|
|
308
307
|
}
|
|
308
|
+
} else if (binOp === '&') {
|
|
309
|
+
if (typeof leftValue === 'number' && Math.floor(leftValue) === leftValue &&
|
|
310
|
+
typeof rightValue === 'number' && Math.floor(rightValue) === rightValue) {
|
|
311
|
+
return leftValue & rightValue;
|
|
312
|
+
}
|
|
313
|
+
} else if (binOp === '|') {
|
|
314
|
+
if (typeof leftValue === 'number' && Math.floor(leftValue) === leftValue &&
|
|
315
|
+
typeof rightValue === 'number' && Math.floor(rightValue) === rightValue) {
|
|
316
|
+
return leftValue | rightValue;
|
|
317
|
+
}
|
|
318
|
+
} else if (binOp === '^') {
|
|
319
|
+
if (typeof leftValue === 'number' && Math.floor(leftValue) === leftValue &&
|
|
320
|
+
typeof rightValue === 'number' && Math.floor(rightValue) === rightValue) {
|
|
321
|
+
return leftValue ^ rightValue;
|
|
322
|
+
}
|
|
323
|
+
} else if (binOp === '<<') {
|
|
324
|
+
if (typeof leftValue === 'number' && Math.floor(leftValue) === leftValue &&
|
|
325
|
+
typeof rightValue === 'number' && Math.floor(rightValue) === rightValue) {
|
|
326
|
+
return leftValue << rightValue;
|
|
327
|
+
}
|
|
328
|
+
} else {
|
|
329
|
+
// if (binOp === '>>')
|
|
330
|
+
if (typeof leftValue === 'number' && Math.floor(leftValue) === leftValue &&
|
|
331
|
+
typeof rightValue === 'number' && Math.floor(rightValue) === rightValue) {
|
|
332
|
+
return leftValue >> rightValue;
|
|
333
|
+
}
|
|
309
334
|
}
|
|
310
335
|
|
|
311
336
|
// Invalid operation values
|
|
@@ -318,8 +343,15 @@ export function evaluateExpression(expr, options = null, locals = null, builtins
|
|
|
318
343
|
const value = evaluateExpression(expr.unary.expr, options, locals, builtins);
|
|
319
344
|
if (unaryOp === '!') {
|
|
320
345
|
return !valueBoolean(value);
|
|
321
|
-
} else if (unaryOp === '-'
|
|
322
|
-
|
|
346
|
+
} else if (unaryOp === '-') {
|
|
347
|
+
if (typeof value === 'number') {
|
|
348
|
+
return -value;
|
|
349
|
+
}
|
|
350
|
+
} else {
|
|
351
|
+
// if (unaryOp === '~'
|
|
352
|
+
if (typeof value === 'number' && Math.floor(value) === value) {
|
|
353
|
+
return ~value;
|
|
354
|
+
}
|
|
323
355
|
}
|
|
324
356
|
|
|
325
357
|
// Invalid operation value
|
package/lib/runtimeAsync.js
CHANGED
|
@@ -371,12 +371,37 @@ export async function evaluateExpressionAsync(expr, options = null, locals = nul
|
|
|
371
371
|
if (typeof leftValue === 'number' && typeof rightValue === 'number') {
|
|
372
372
|
return leftValue % rightValue;
|
|
373
373
|
}
|
|
374
|
-
} else {
|
|
375
|
-
// binOp === '**'
|
|
374
|
+
} else if (binOp === '**') {
|
|
376
375
|
// number ** number
|
|
377
376
|
if (typeof leftValue === 'number' && typeof rightValue === 'number') {
|
|
378
377
|
return leftValue ** rightValue;
|
|
379
378
|
}
|
|
379
|
+
} else if (binOp === '&') {
|
|
380
|
+
if (typeof leftValue === 'number' && Math.floor(leftValue) === leftValue &&
|
|
381
|
+
typeof rightValue === 'number' && Math.floor(rightValue) === rightValue) {
|
|
382
|
+
return leftValue & rightValue;
|
|
383
|
+
}
|
|
384
|
+
} else if (binOp === '|') {
|
|
385
|
+
if (typeof leftValue === 'number' && Math.floor(leftValue) === leftValue &&
|
|
386
|
+
typeof rightValue === 'number' && Math.floor(rightValue) === rightValue) {
|
|
387
|
+
return leftValue | rightValue;
|
|
388
|
+
}
|
|
389
|
+
} else if (binOp === '^') {
|
|
390
|
+
if (typeof leftValue === 'number' && Math.floor(leftValue) === leftValue &&
|
|
391
|
+
typeof rightValue === 'number' && Math.floor(rightValue) === rightValue) {
|
|
392
|
+
return leftValue ^ rightValue;
|
|
393
|
+
}
|
|
394
|
+
} else if (binOp === '<<') {
|
|
395
|
+
if (typeof leftValue === 'number' && Math.floor(leftValue) === leftValue &&
|
|
396
|
+
typeof rightValue === 'number' && Math.floor(rightValue) === rightValue) {
|
|
397
|
+
return leftValue << rightValue;
|
|
398
|
+
}
|
|
399
|
+
} else {
|
|
400
|
+
// if (binOp === '>>')
|
|
401
|
+
if (typeof leftValue === 'number' && Math.floor(leftValue) === leftValue &&
|
|
402
|
+
typeof rightValue === 'number' && Math.floor(rightValue) === rightValue) {
|
|
403
|
+
return leftValue >> rightValue;
|
|
404
|
+
}
|
|
380
405
|
}
|
|
381
406
|
|
|
382
407
|
// Invalid operation values
|
|
@@ -389,8 +414,15 @@ export async function evaluateExpressionAsync(expr, options = null, locals = nul
|
|
|
389
414
|
const value = await evaluateExpressionAsync(expr.unary.expr, options, locals, builtins);
|
|
390
415
|
if (unaryOp === '!') {
|
|
391
416
|
return !valueBoolean(value);
|
|
392
|
-
} else if (unaryOp === '-'
|
|
393
|
-
|
|
417
|
+
} else if (unaryOp === '-') {
|
|
418
|
+
if (typeof value === 'number') {
|
|
419
|
+
return -value;
|
|
420
|
+
}
|
|
421
|
+
} else {
|
|
422
|
+
// if (unaryOp === '~'
|
|
423
|
+
if (typeof value === 'number' && Math.floor(value) === value) {
|
|
424
|
+
return ~value;
|
|
425
|
+
}
|
|
394
426
|
}
|
|
395
427
|
|
|
396
428
|
// Invalid operation value
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "bare-script",
|
|
4
|
-
"version": "3.
|
|
4
|
+
"version": "3.5.0",
|
|
5
5
|
"description": "BareScript; a lightweight scripting and expression language",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"expression",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
33
33
|
"c8": "~10.1",
|
|
34
|
-
"eslint": "~9.
|
|
34
|
+
"eslint": "~9.35",
|
|
35
35
|
"jsdoc": "~4.0"
|
|
36
36
|
}
|
|
37
37
|
}
|