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 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
- ~~~ javascript
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
- ~~~ javascript
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
- ~~~ javascript
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
- ~~~ markdown-script
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='BareScript')
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 = (delim === '<' ? matchInclude.groups.url : matchInclude.groups.url.replace(rExprStringEscape, '$1'));
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(rExprStringEscape, '$1');
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(rExprStringDoubleEscape, '$1');
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
- const matchVariableEx = exprText.match(rExprVariableEx);
696
- if (matchVariableEx !== null) {
697
- const variableName = matchVariableEx[1].replace(rExprVariableExEscape, '$1');
698
- const expr = {'variable': variableName};
699
- return [expr, exprText.slice(matchVariableEx[0].length)];
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
  *
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "bare-script",
4
- "version": "3.6.0",
4
+ "version": "3.7.0",
5
5
  "description": "BareScript; a lightweight scripting and expression language",
6
6
  "keywords": [
7
7
  "expression",