bare-script 3.6.0 → 3.7.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/README.md +19 -19
- package/lib/library.js +19 -1
- package/lib/parser.js +141 -29
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -36,7 +36,7 @@ function or the
|
|
|
36
36
|
[executeScriptAsync](https://craigahobbs.github.io/bare-script/module-lib_runtimeAsync.html#.executeScriptAsync)
|
|
37
37
|
function. For example:
|
|
38
38
|
|
|
39
|
-
|
|
39
|
+
``` javascript
|
|
40
40
|
import {executeScript} from 'bare-script/lib/runtime.js';
|
|
41
41
|
import {parseScript} from 'bare-script/lib/parser.js';
|
|
42
42
|
|
|
@@ -53,13 +53,13 @@ return N + ' times 2 is ' + double(N)
|
|
|
53
53
|
// Execute the script
|
|
54
54
|
const globals = {'N': 10};
|
|
55
55
|
console.log(executeScript(script, {globals}));
|
|
56
|
-
|
|
56
|
+
```
|
|
57
57
|
|
|
58
58
|
This outputs:
|
|
59
59
|
|
|
60
|
-
|
|
60
|
+
```
|
|
61
61
|
10 times 2 is 20
|
|
62
|
-
|
|
62
|
+
```
|
|
63
63
|
|
|
64
64
|
|
|
65
65
|
### The BareScript Library
|
|
@@ -73,7 +73,7 @@ of the
|
|
|
73
73
|
[arrayLength](https://craigahobbs.github.io/bare-script/library/#var.vGroup='Array'&arraylength)
|
|
74
74
|
functions.
|
|
75
75
|
|
|
76
|
-
|
|
76
|
+
``` javascript
|
|
77
77
|
import {executeScriptAsync} from 'bare-script/lib/runtimeAsync.js';
|
|
78
78
|
import {parseScript} from 'bare-script/lib/parser.js';
|
|
79
79
|
|
|
@@ -88,13 +88,13 @@ return 'The BareScript Library has ' + arrayLength(objectGet(docs, 'functions'))
|
|
|
88
88
|
|
|
89
89
|
// Execute the script
|
|
90
90
|
console.log(await executeScriptAsync(script, {'fetchFn': fetch}));
|
|
91
|
-
|
|
91
|
+
```
|
|
92
92
|
|
|
93
93
|
This outputs:
|
|
94
94
|
|
|
95
|
-
|
|
95
|
+
```
|
|
96
96
|
The BareScript Library has 105 functions
|
|
97
|
-
|
|
97
|
+
```
|
|
98
98
|
|
|
99
99
|
|
|
100
100
|
## Evaluating BareScript Expressions
|
|
@@ -115,7 +115,7 @@ a set of built-in, spreadsheet-like functions.
|
|
|
115
115
|
|
|
116
116
|
For example:
|
|
117
117
|
|
|
118
|
-
|
|
118
|
+
``` javascript
|
|
119
119
|
import {evaluateExpression} from 'bare-script/lib/runtime.js';
|
|
120
120
|
import {parseExpression} from 'bare-script/lib/parser.js';
|
|
121
121
|
|
|
@@ -125,13 +125,13 @@ const expr = parseExpression('2 * max(a, b, c)');
|
|
|
125
125
|
// Evaluate the expression
|
|
126
126
|
const variables = {'a': 1, 'b': 2, 'c': 3};
|
|
127
127
|
console.log(evaluateExpression(expr, null, variables))
|
|
128
|
-
|
|
128
|
+
```
|
|
129
129
|
|
|
130
130
|
This outputs:
|
|
131
131
|
|
|
132
|
-
|
|
132
|
+
```
|
|
133
133
|
6
|
|
134
|
-
|
|
134
|
+
```
|
|
135
135
|
|
|
136
136
|
|
|
137
137
|
## The BareScript Command-Line Interface (CLI)
|
|
@@ -139,9 +139,9 @@ This outputs:
|
|
|
139
139
|
You can run BareScript from the command line using the BareScript CLI, "bare". BareScript script
|
|
140
140
|
files use the ".bare" file extension.
|
|
141
141
|
|
|
142
|
-
|
|
142
|
+
```
|
|
143
143
|
bare script.bare
|
|
144
|
-
|
|
144
|
+
```
|
|
145
145
|
|
|
146
146
|
**Note:** In the BareScript CLI, import statements and the
|
|
147
147
|
[systemFetch](https://craigahobbs.github.io/bare-script/library/#var.vGroup='System'&systemfetch)
|
|
@@ -163,15 +163,15 @@ with functions for dynamically rendering Markdown text, drawing SVG images, etc.
|
|
|
163
163
|
|
|
164
164
|
For example:
|
|
165
165
|
|
|
166
|
-
|
|
166
|
+
~~~
|
|
167
167
|
# Markdown Application
|
|
168
168
|
|
|
169
169
|
This is a Markdown document with embedded BareScript:
|
|
170
170
|
|
|
171
|
-
|
|
171
|
+
``` markdown-script
|
|
172
172
|
markdownPrint('Hello, Markdown!')
|
|
173
|
-
~~~
|
|
174
173
|
```
|
|
174
|
+
~~~
|
|
175
175
|
|
|
176
176
|
|
|
177
177
|
## Development
|
|
@@ -179,6 +179,6 @@ markdownPrint('Hello, Markdown!')
|
|
|
179
179
|
This package is developed using [javascript-build](https://github.com/craigahobbs/javascript-build#readme).
|
|
180
180
|
It was started using [javascript-template](https://github.com/craigahobbs/javascript-template#readme) as follows:
|
|
181
181
|
|
|
182
|
-
|
|
182
|
+
```
|
|
183
183
|
template-specialize javascript-template/template/ bare-script/ -k package bare-script -k name 'Craig A. Hobbs' -k email 'craigahobbs@gmail.com' -k github 'craigahobbs' -k noapp 1
|
|
184
|
-
|
|
184
|
+
```
|
package/lib/library.js
CHANGED
|
@@ -78,6 +78,21 @@ const arrayExtendArgs = valueArgsModel([
|
|
|
78
78
|
]);
|
|
79
79
|
|
|
80
80
|
|
|
81
|
+
// $function: arrayFlat
|
|
82
|
+
// $group: Array
|
|
83
|
+
// $doc: Flat an array hierarchy
|
|
84
|
+
// $arg array: The array to flat
|
|
85
|
+
// $return: The flated array
|
|
86
|
+
function arrayFlat(args) {
|
|
87
|
+
const [array] = valueArgsValidate(arrayFlatArgs, args);
|
|
88
|
+
return array.flat(Infinity);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const arrayFlatArgs = valueArgsModel([
|
|
92
|
+
{'name': 'array', 'type': 'array'}
|
|
93
|
+
]);
|
|
94
|
+
|
|
95
|
+
|
|
81
96
|
// $function: arrayGet
|
|
82
97
|
// $group: Array
|
|
83
98
|
// $doc: Get an array element
|
|
@@ -365,7 +380,7 @@ export const coverageGlobalName = '__bareScriptCoverage';
|
|
|
365
380
|
// $function: coverageGlobalGet
|
|
366
381
|
// $group: Coverage
|
|
367
382
|
// $doc: Get the coverage global object
|
|
368
|
-
// $return: The [coverage global object](https://craigahobbs.github.io/bare-script/model/#var.vName='
|
|
383
|
+
// $return: The [coverage global object](https://craigahobbs.github.io/bare-script/model/#var.vName='CoverageGlobal')
|
|
369
384
|
function coverageGlobalGet(unusedArgs, options) {
|
|
370
385
|
const globals = (options !== null ? (options.globals ?? null) : null);
|
|
371
386
|
return globals !== null ? (globals[coverageGlobalName] ?? null) : null;
|
|
@@ -2133,6 +2148,7 @@ export const scriptFunctions = {
|
|
|
2133
2148
|
arrayCopy,
|
|
2134
2149
|
arrayDelete,
|
|
2135
2150
|
arrayExtend,
|
|
2151
|
+
arrayFlat,
|
|
2136
2152
|
arrayGet,
|
|
2137
2153
|
arrayIndexOf,
|
|
2138
2154
|
arrayJoin,
|
|
@@ -2247,6 +2263,7 @@ export const scriptFunctions = {
|
|
|
2247
2263
|
export const expressionFunctionMap = {
|
|
2248
2264
|
'abs': 'mathAbs',
|
|
2249
2265
|
'acos': 'mathAcos',
|
|
2266
|
+
'arrayNew': 'arrayNew',
|
|
2250
2267
|
'asin': 'mathAsin',
|
|
2251
2268
|
'atan': 'mathAtan',
|
|
2252
2269
|
'atan2': 'mathAtan2',
|
|
@@ -2271,6 +2288,7 @@ export const expressionFunctionMap = {
|
|
|
2271
2288
|
'minute': 'datetimeMinute',
|
|
2272
2289
|
'month': 'datetimeMonth',
|
|
2273
2290
|
'now': 'datetimeNow',
|
|
2291
|
+
'objectNew': 'objectNew',
|
|
2274
2292
|
'parseInt': 'numberParseInt',
|
|
2275
2293
|
'parseFloat': 'numberParseFloat',
|
|
2276
2294
|
'pi': 'mathPi',
|
package/lib/parser.js
CHANGED
|
@@ -82,7 +82,7 @@ export function parseScript(scriptText, startLineNumber = 1, scriptName = null)
|
|
|
82
82
|
const exprStatement = {
|
|
83
83
|
'expr': {
|
|
84
84
|
'name': matchAssignment.groups.name,
|
|
85
|
-
'expr': parseExpression(matchAssignment.groups.expr, lineNumber, scriptName),
|
|
85
|
+
'expr': parseExpression(matchAssignment.groups.expr, lineNumber, scriptName, true),
|
|
86
86
|
...statementBase
|
|
87
87
|
}
|
|
88
88
|
};
|
|
@@ -151,7 +151,7 @@ export function parseScript(scriptText, startLineNumber = 1, scriptName = null)
|
|
|
151
151
|
const ifthen = {
|
|
152
152
|
'jump': {
|
|
153
153
|
'label': `__bareScriptIf${labelIndex}`,
|
|
154
|
-
'expr': {'unary': {'op': '!', 'expr': parseExpression(matchIfBegin.groups.expr, lineNumber, scriptName)}},
|
|
154
|
+
'expr': {'unary': {'op': '!', 'expr': parseExpression(matchIfBegin.groups.expr, lineNumber, scriptName, true)}},
|
|
155
155
|
...statementBase
|
|
156
156
|
},
|
|
157
157
|
'done': `__bareScriptDone${labelIndex}`,
|
|
@@ -186,7 +186,7 @@ export function parseScript(scriptText, startLineNumber = 1, scriptName = null)
|
|
|
186
186
|
const prevLabel = ifthen.jump.label;
|
|
187
187
|
ifthen.jump = {
|
|
188
188
|
'label': `__bareScriptIf${labelIndex}`,
|
|
189
|
-
'expr': {'unary': {'op': '!', 'expr': parseExpression(matchIfElseIf.groups.expr, lineNumber, scriptName)}},
|
|
189
|
+
'expr': {'unary': {'op': '!', 'expr': parseExpression(matchIfElseIf.groups.expr, lineNumber, scriptName, true)}},
|
|
190
190
|
...statementBase
|
|
191
191
|
};
|
|
192
192
|
labelIndex += 1;
|
|
@@ -252,7 +252,7 @@ export function parseScript(scriptText, startLineNumber = 1, scriptName = null)
|
|
|
252
252
|
'loop': `__bareScriptLoop${labelIndex}`,
|
|
253
253
|
'continue': `__bareScriptLoop${labelIndex}`,
|
|
254
254
|
'done': `__bareScriptDone${labelIndex}`,
|
|
255
|
-
'expr': parseExpression(matchWhileBegin.groups.expr, lineNumber, scriptName),
|
|
255
|
+
'expr': parseExpression(matchWhileBegin.groups.expr, lineNumber, scriptName, true),
|
|
256
256
|
line,
|
|
257
257
|
'lineNumber': startLineNumber + ixLine
|
|
258
258
|
};
|
|
@@ -307,7 +307,7 @@ export function parseScript(scriptText, startLineNumber = 1, scriptName = null)
|
|
|
307
307
|
statements.push(
|
|
308
308
|
{'expr': {
|
|
309
309
|
'name': foreach.values,
|
|
310
|
-
'expr': parseExpression(matchForBegin.groups.values, lineNumber, scriptName),
|
|
310
|
+
'expr': parseExpression(matchForBegin.groups.values, lineNumber, scriptName, true),
|
|
311
311
|
...statementBase
|
|
312
312
|
}},
|
|
313
313
|
{'expr': {
|
|
@@ -407,7 +407,7 @@ export function parseScript(scriptText, startLineNumber = 1, scriptName = null)
|
|
|
407
407
|
const jumpStatement = {'jump': {'label': matchJump.groups.name, ...statementBase}};
|
|
408
408
|
if (typeof matchJump.groups.expr !== 'undefined') {
|
|
409
409
|
try {
|
|
410
|
-
jumpStatement.jump.expr = parseExpression(matchJump.groups.expr, lineNumber, scriptName);
|
|
410
|
+
jumpStatement.jump.expr = parseExpression(matchJump.groups.expr, lineNumber, scriptName, true);
|
|
411
411
|
} catch (error) {
|
|
412
412
|
const columnNumber = matchJump.groups.jump.length - matchJump.groups.expr.length - 1 + error.columnNumber;
|
|
413
413
|
throw new BareScriptParserError(error.error, line, columnNumber, startLineNumber + ixLine, scriptName);
|
|
@@ -423,7 +423,7 @@ export function parseScript(scriptText, startLineNumber = 1, scriptName = null)
|
|
|
423
423
|
const returnStatement = {'return': {...statementBase}};
|
|
424
424
|
if (typeof matchReturn.groups.expr !== 'undefined') {
|
|
425
425
|
try {
|
|
426
|
-
returnStatement.return.expr = parseExpression(matchReturn.groups.expr, lineNumber, scriptName);
|
|
426
|
+
returnStatement.return.expr = parseExpression(matchReturn.groups.expr, lineNumber, scriptName, true);
|
|
427
427
|
} catch (error) {
|
|
428
428
|
const columnNumber = matchReturn.groups.return.length - matchReturn.groups.expr.length + error.columnNumber;
|
|
429
429
|
throw new BareScriptParserError(error.error, line, columnNumber, startLineNumber + ixLine, scriptName);
|
|
@@ -437,7 +437,9 @@ export function parseScript(scriptText, startLineNumber = 1, scriptName = null)
|
|
|
437
437
|
const matchInclude = line.match(rScriptInclude) || line.match(rScriptIncludeSystem);
|
|
438
438
|
if (matchInclude !== null) {
|
|
439
439
|
const {delim} = matchInclude.groups;
|
|
440
|
-
const url = (
|
|
440
|
+
const url = (
|
|
441
|
+
delim === '<' ? matchInclude.groups.url : matchInclude.groups.url.replace(rExprStringEscapes, replaceStringEscape)
|
|
442
|
+
);
|
|
441
443
|
let includeStatement = (statements.length ? statements[statements.length - 1] : null);
|
|
442
444
|
if (includeStatement === null || !('include' in includeStatement)) {
|
|
443
445
|
includeStatement = {'include': {'includes': [], ...statementBase}};
|
|
@@ -451,7 +453,7 @@ export function parseScript(scriptText, startLineNumber = 1, scriptName = null)
|
|
|
451
453
|
|
|
452
454
|
// Expression
|
|
453
455
|
try {
|
|
454
|
-
const exprStatement = {'expr': {'expr': parseExpression(line, lineNumber, scriptName), ...statementBase}};
|
|
456
|
+
const exprStatement = {'expr': {'expr': parseExpression(line, lineNumber, scriptName, true), ...statementBase}};
|
|
455
457
|
statements.push(exprStatement);
|
|
456
458
|
} catch (error) {
|
|
457
459
|
throw new BareScriptParserError(error.error, line, error.columnNumber, startLineNumber + ixLine, scriptName);
|
|
@@ -505,12 +507,15 @@ const rScriptContinue = new RegExp(`^\\s*continue${rPartComment}`);
|
|
|
505
507
|
* Parse a BareScript expression
|
|
506
508
|
*
|
|
507
509
|
* @param {string} exprText - The [expression text](./language/#expressions)
|
|
510
|
+
* @param {number} [lineNumber = 1] - The script line number
|
|
511
|
+
* @param {?string} [scriptName = null] - The script name
|
|
512
|
+
* @param {boolean} [arrayLiterals = false] - If True, allow parsing of array literals
|
|
508
513
|
* @returns {Object} The [expression model](./model/#var.vName='Expression')
|
|
509
514
|
* @throws [BareScriptParserError]{@link module:lib/parser.BareScriptParserError}
|
|
510
515
|
*/
|
|
511
|
-
export function parseExpression(exprText, lineNumber = null, scriptName = null) {
|
|
516
|
+
export function parseExpression(exprText, lineNumber = null, scriptName = null, arrayLiterals = false) {
|
|
512
517
|
try {
|
|
513
|
-
const [expr, nextText] = parseBinaryExpression(exprText, null);
|
|
518
|
+
const [expr, nextText] = parseBinaryExpression(exprText, null, arrayLiterals);
|
|
514
519
|
if (nextText.trim() !== '') {
|
|
515
520
|
throw new BareScriptParserError('Syntax error', nextText, 1, lineNumber, scriptName);
|
|
516
521
|
}
|
|
@@ -523,7 +528,7 @@ export function parseExpression(exprText, lineNumber = null, scriptName = null)
|
|
|
523
528
|
|
|
524
529
|
|
|
525
530
|
// Helper function to parse a binary operator expression chain
|
|
526
|
-
function parseBinaryExpression(exprText, binLeftExpr) {
|
|
531
|
+
function parseBinaryExpression(exprText, binLeftExpr, arrayLiterals) {
|
|
527
532
|
// Parse the binary operator's left unary expression if none was passed
|
|
528
533
|
let leftExpr;
|
|
529
534
|
let binText;
|
|
@@ -531,7 +536,7 @@ function parseBinaryExpression(exprText, binLeftExpr) {
|
|
|
531
536
|
binText = exprText;
|
|
532
537
|
leftExpr = binLeftExpr;
|
|
533
538
|
} else {
|
|
534
|
-
[leftExpr, binText] = parseUnaryExpression(exprText);
|
|
539
|
+
[leftExpr, binText] = parseUnaryExpression(exprText, arrayLiterals);
|
|
535
540
|
}
|
|
536
541
|
|
|
537
542
|
// Match a binary operator - if not found, return the left expression
|
|
@@ -548,7 +553,7 @@ function parseBinaryExpression(exprText, binLeftExpr) {
|
|
|
548
553
|
const rightText = binText.slice(matchBinaryOp[0].length);
|
|
549
554
|
|
|
550
555
|
// Parse the right sub-expression
|
|
551
|
-
const [rightExpr, nextText] = parseUnaryExpression(rightText);
|
|
556
|
+
const [rightExpr, nextText] = parseUnaryExpression(rightText, arrayLiterals);
|
|
552
557
|
|
|
553
558
|
// Create the binary expression - re-order for binary operators as necessary
|
|
554
559
|
let binExpr;
|
|
@@ -566,7 +571,7 @@ function parseBinaryExpression(exprText, binLeftExpr) {
|
|
|
566
571
|
}
|
|
567
572
|
|
|
568
573
|
// Parse the next binary expression in the chain
|
|
569
|
-
return parseBinaryExpression(nextText, binExpr);
|
|
574
|
+
return parseBinaryExpression(nextText, binExpr, arrayLiterals);
|
|
570
575
|
}
|
|
571
576
|
|
|
572
577
|
|
|
@@ -595,12 +600,12 @@ const binaryReorder = {
|
|
|
595
600
|
|
|
596
601
|
|
|
597
602
|
// Helper function to parse a unary expression
|
|
598
|
-
function parseUnaryExpression(exprText) {
|
|
603
|
+
function parseUnaryExpression(exprText, arrayLiterals) {
|
|
599
604
|
// Group open?
|
|
600
605
|
const matchGroupOpen = exprText.match(rExprGroupOpen);
|
|
601
606
|
if (matchGroupOpen !== null) {
|
|
602
607
|
const groupText = exprText.slice(matchGroupOpen[0].length);
|
|
603
|
-
const [expr, nextText] = parseBinaryExpression(groupText, null);
|
|
608
|
+
const [expr, nextText] = parseBinaryExpression(groupText, null, arrayLiterals);
|
|
604
609
|
const matchGroupClose = nextText.match(rExprGroupClose);
|
|
605
610
|
if (matchGroupClose === null) {
|
|
606
611
|
throw new BareScriptParserError('Unmatched parenthesis', exprText, 1, null, null);
|
|
@@ -620,7 +625,7 @@ function parseUnaryExpression(exprText) {
|
|
|
620
625
|
// String?
|
|
621
626
|
const matchString = exprText.match(rExprString);
|
|
622
627
|
if (matchString !== null) {
|
|
623
|
-
const string = matchString[1].replace(
|
|
628
|
+
const string = matchString[1].replace(rExprStringEscapes, replaceStringEscape);
|
|
624
629
|
const expr = {'string': string};
|
|
625
630
|
return [expr, exprText.slice(matchString[0].length)];
|
|
626
631
|
}
|
|
@@ -628,7 +633,7 @@ function parseUnaryExpression(exprText) {
|
|
|
628
633
|
// String (double quotes)?
|
|
629
634
|
const matchStringDouble = exprText.match(rExprStringDouble);
|
|
630
635
|
if (matchStringDouble !== null) {
|
|
631
|
-
const string = matchStringDouble[1].replace(
|
|
636
|
+
const string = matchStringDouble[1].replace(rExprStringEscapes, replaceStringEscape);
|
|
632
637
|
const expr = {'string': string};
|
|
633
638
|
return [expr, exprText.slice(matchStringDouble[0].length)];
|
|
634
639
|
}
|
|
@@ -637,7 +642,7 @@ function parseUnaryExpression(exprText) {
|
|
|
637
642
|
const matchUnary = exprText.match(rExprUnaryOp);
|
|
638
643
|
if (matchUnary !== null) {
|
|
639
644
|
const unaryText = exprText.slice(matchUnary[0].length);
|
|
640
|
-
const [expr, nextText] = parseUnaryExpression(unaryText);
|
|
645
|
+
const [expr, nextText] = parseUnaryExpression(unaryText, arrayLiterals);
|
|
641
646
|
const unaryExpr = {
|
|
642
647
|
'unary': {
|
|
643
648
|
'op': matchUnary[1],
|
|
@@ -670,9 +675,9 @@ function parseUnaryExpression(exprText) {
|
|
|
670
675
|
}
|
|
671
676
|
|
|
672
677
|
// Get the argument
|
|
673
|
-
const [argExpr, nextArgText] = parseBinaryExpression(argText, null);
|
|
674
|
-
args.push(argExpr);
|
|
678
|
+
const [argExpr, nextArgText] = parseBinaryExpression(argText, null, arrayLiterals);
|
|
675
679
|
argText = nextArgText;
|
|
680
|
+
args.push(argExpr);
|
|
676
681
|
}
|
|
677
682
|
|
|
678
683
|
const fnExpr = {
|
|
@@ -684,6 +689,84 @@ function parseUnaryExpression(exprText) {
|
|
|
684
689
|
return [fnExpr, argText];
|
|
685
690
|
}
|
|
686
691
|
|
|
692
|
+
// Object creation?
|
|
693
|
+
const matchObjectOpen = exprText.match(rExprObjectOpen);
|
|
694
|
+
if (matchObjectOpen !== null) {
|
|
695
|
+
let argText = exprText.slice(matchObjectOpen[0].length);
|
|
696
|
+
const args = [];
|
|
697
|
+
while (true) {
|
|
698
|
+
// Object close?
|
|
699
|
+
const matchObjectClose = argText.match(rExprObjectClose);
|
|
700
|
+
if (matchObjectClose !== null) {
|
|
701
|
+
argText = argText.slice(matchObjectClose[0].length);
|
|
702
|
+
break;
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
// Object key/value separator
|
|
706
|
+
if (args.length !== 0) {
|
|
707
|
+
const matchObjectSeparator = argText.match(rExprObjectSeparator2);
|
|
708
|
+
if (matchObjectSeparator === null) {
|
|
709
|
+
throw new BareScriptParserError('Syntax error', argText, 1, null, null);
|
|
710
|
+
}
|
|
711
|
+
argText = argText.slice(matchObjectSeparator[0].length);
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
// Get the key
|
|
715
|
+
const [argKey, nextArgText] = parseBinaryExpression(argText, null, arrayLiterals);
|
|
716
|
+
argText = nextArgText;
|
|
717
|
+
args.push(argKey);
|
|
718
|
+
|
|
719
|
+
// Object key separator
|
|
720
|
+
if (args.length !== 0) {
|
|
721
|
+
const matchObjectSeparator = argText.match(rExprObjectSeparator);
|
|
722
|
+
if (matchObjectSeparator === null) {
|
|
723
|
+
throw new BareScriptParserError('Syntax error', argText, 1, null, null);
|
|
724
|
+
}
|
|
725
|
+
argText = argText.slice(matchObjectSeparator[0].length);
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
// Get the value
|
|
729
|
+
const [argValue, nextArgText2] = parseBinaryExpression(argText, null, arrayLiterals);
|
|
730
|
+
argText = nextArgText2;
|
|
731
|
+
args.push(argValue);
|
|
732
|
+
}
|
|
733
|
+
const fnExpr = {'function': {'name': 'objectNew', 'args': args}};
|
|
734
|
+
return [fnExpr, argText];
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
// Array creation?
|
|
738
|
+
if (arrayLiterals) {
|
|
739
|
+
const matchArrayOpen = exprText.match(rExprArrayOpen);
|
|
740
|
+
if (matchArrayOpen !== null) {
|
|
741
|
+
let argText = exprText.slice(matchArrayOpen[0].length);
|
|
742
|
+
const args = [];
|
|
743
|
+
while (true) {
|
|
744
|
+
// Array close?
|
|
745
|
+
const matchArrayClose = argText.match(rExprArrayClose);
|
|
746
|
+
if (matchArrayClose !== null) {
|
|
747
|
+
argText = argText.slice(matchArrayClose[0].length);
|
|
748
|
+
break;
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
// Array value separator
|
|
752
|
+
if (args.length !== 0) {
|
|
753
|
+
const matchArraySeparator = argText.match(rExprArraySeparator);
|
|
754
|
+
if (matchArraySeparator === null) {
|
|
755
|
+
throw new BareScriptParserError('Syntax error', argText, 1, null, null);
|
|
756
|
+
}
|
|
757
|
+
argText = argText.slice(matchArraySeparator[0].length);
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
// Get the value
|
|
761
|
+
const [argValue, nextArgText2] = parseBinaryExpression(argText, null, arrayLiterals);
|
|
762
|
+
argText = nextArgText2;
|
|
763
|
+
args.push(argValue);
|
|
764
|
+
}
|
|
765
|
+
const fnExpr = {'function': {'name': 'arrayNew', 'args': args}};
|
|
766
|
+
return [fnExpr, argText];
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
|
|
687
770
|
// Variable?
|
|
688
771
|
const matchVariable = exprText.match(rExprVariable);
|
|
689
772
|
if (matchVariable !== null) {
|
|
@@ -692,11 +775,13 @@ function parseUnaryExpression(exprText) {
|
|
|
692
775
|
}
|
|
693
776
|
|
|
694
777
|
// Variable (brackets)?
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
778
|
+
if (!arrayLiterals) {
|
|
779
|
+
const matchVariableEx = exprText.match(rExprVariableEx);
|
|
780
|
+
if (matchVariableEx !== null) {
|
|
781
|
+
const variableName = matchVariableEx[1].replace(rExprVariableExEscape, '$1');
|
|
782
|
+
const expr = {'variable': variableName};
|
|
783
|
+
return [expr, exprText.slice(matchVariableEx[0].length)];
|
|
784
|
+
}
|
|
700
785
|
}
|
|
701
786
|
|
|
702
787
|
throw new BareScriptParserError('Syntax error', exprText, 1, null, null);
|
|
@@ -713,15 +798,42 @@ const rExprFunctionClose = /^\s*\)/;
|
|
|
713
798
|
const rExprGroupOpen = /^\s*\(/;
|
|
714
799
|
const rExprGroupClose = /^\s*\)/;
|
|
715
800
|
const rExprNumber = /^\s*(0x[A-Fa-f0-9]+|[+-]?\d+(?:\.\d*)?(?:e[+-]?\d+)?)/;
|
|
801
|
+
const rExprArrayOpen = /^\s*\[/;
|
|
802
|
+
const rExprArraySeparator = /^\s*,/;
|
|
803
|
+
const rExprArrayClose = /^\s*\]/;
|
|
804
|
+
const rExprObjectOpen = /^\s*\{/;
|
|
805
|
+
const rExprObjectSeparator = /^\s*:/;
|
|
806
|
+
const rExprObjectSeparator2 = /^\s*,/;
|
|
807
|
+
const rExprObjectClose = /^\s*\}/;
|
|
716
808
|
const rExprString = /^\s*'((?:\\\\|\\'|[^'])*)'/;
|
|
717
|
-
const rExprStringEscape = /\\([\\'])/g;
|
|
718
809
|
const rExprStringDouble = /^\s*"((?:\\\\|\\"|[^"])*)"/;
|
|
719
|
-
const rExprStringDoubleEscape = /\\([\\"])/g;
|
|
720
810
|
const rExprVariable = /^\s*([A-Za-z_]\w*)/;
|
|
721
811
|
const rExprVariableEx = /^\s*\[\s*((?:\\\]|[^\]])+)\s*\]/;
|
|
722
812
|
const rExprVariableExEscape = /\\([\\\]])/g;
|
|
723
813
|
|
|
724
814
|
|
|
815
|
+
// String literal escapes
|
|
816
|
+
const rExprStringEscapes = /(?<!\\)\\([nrtbf'"\\]|u[0-9a-fA-F]{4})/g;
|
|
817
|
+
|
|
818
|
+
function replaceStringEscape(unusedMatch, esc) {
|
|
819
|
+
if (esc.startsWith('u')) {
|
|
820
|
+
return String.fromCharCode(parseInt(esc.slice(1), 16));
|
|
821
|
+
}
|
|
822
|
+
return exprStringEscapes[esc];
|
|
823
|
+
}
|
|
824
|
+
|
|
825
|
+
const exprStringEscapes = {
|
|
826
|
+
'n': '\n',
|
|
827
|
+
'r': '\r',
|
|
828
|
+
't': '\t',
|
|
829
|
+
'b': '\b',
|
|
830
|
+
'f': '\f',
|
|
831
|
+
"'": "'",
|
|
832
|
+
'"': '"',
|
|
833
|
+
'\\': '\\'
|
|
834
|
+
};
|
|
835
|
+
|
|
836
|
+
|
|
725
837
|
/**
|
|
726
838
|
* A BareScript parser error
|
|
727
839
|
*
|