bare-script 3.5.4 → 3.6.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/parser.js CHANGED
@@ -9,14 +9,18 @@
9
9
  *
10
10
  * @param {string|string[]} scriptText - The [script text](./language/)
11
11
  * @param {number} [startLineNumber = 1] - The script's starting line number
12
+ * @param {?string} [scriptName = null] - The script name
12
13
  * @returns {Object} The [BareScript model](./model/#var.vName='BareScript')
13
14
  * @throws [BareScriptParserError]{@link module:lib/parser.BareScriptParserError}
14
15
  */
15
- export function parseScript(scriptText, startLineNumber = 1) {
16
- const script = {'statements': []};
16
+ export function parseScript(scriptText, startLineNumber = 1, scriptName = null) {
17
+ const lines = [];
18
+ const script = {'statements': [], 'scriptLines': lines};
19
+ if (scriptName !== null) {
20
+ script.scriptName = scriptName;
21
+ }
17
22
 
18
23
  // Line-split all script text
19
- const lines = [];
20
24
  if (typeof scriptText === 'string') {
21
25
  lines.push(...scriptText.split(rScriptLineSplit));
22
26
  } else {
@@ -64,6 +68,13 @@ export function parseScript(scriptText, startLineNumber = 1) {
64
68
  line = linePart;
65
69
  }
66
70
 
71
+ // Base statement members
72
+ const lineNumber = ixLine + 1;
73
+ const statementBase = {lineNumber};
74
+ if (ixLine !== ixLinePart) {
75
+ statementBase.lineCount = (ixLinePart - ixLine) + 1;
76
+ }
77
+
67
78
  // Assignment?
68
79
  const matchAssignment = line.match(rScriptAssignment);
69
80
  if (matchAssignment !== null) {
@@ -71,14 +82,15 @@ export function parseScript(scriptText, startLineNumber = 1) {
71
82
  const exprStatement = {
72
83
  'expr': {
73
84
  'name': matchAssignment.groups.name,
74
- 'expr': parseExpression(matchAssignment.groups.expr)
85
+ 'expr': parseExpression(matchAssignment.groups.expr, lineNumber, scriptName),
86
+ ...statementBase
75
87
  }
76
88
  };
77
89
  statements.push(exprStatement);
78
90
  continue;
79
91
  } catch (error) {
80
92
  const columnNumber = line.length - matchAssignment.groups.expr.length + error.columnNumber;
81
- throw new BareScriptParserError(error.error, line, columnNumber, startLineNumber + ixLine);
93
+ throw new BareScriptParserError(error.error, line, columnNumber, startLineNumber + ixLine, scriptName);
82
94
  }
83
95
  }
84
96
 
@@ -87,7 +99,7 @@ export function parseScript(scriptText, startLineNumber = 1) {
87
99
  if (matchFunctionBegin !== null) {
88
100
  // Nested function definitions are not allowed
89
101
  if (functionDef !== null) {
90
- throw new BareScriptParserError('Nested function definition', line, 1, startLineNumber + ixLine);
102
+ throw new BareScriptParserError('Nested function definition', line, 1, startLineNumber + ixLine, scriptName);
91
103
  }
92
104
 
93
105
  // Add the function definition statement
@@ -95,7 +107,8 @@ export function parseScript(scriptText, startLineNumber = 1) {
95
107
  functionDef = {
96
108
  'function': {
97
109
  'name': matchFunctionBegin.groups.name,
98
- 'statements': []
110
+ 'statements': [],
111
+ ...statementBase
99
112
  }
100
113
  };
101
114
  if (typeof matchFunctionBegin.groups.args !== 'undefined') {
@@ -115,7 +128,7 @@ export function parseScript(scriptText, startLineNumber = 1) {
115
128
  const matchFunctionEnd = line.match(rScriptFunctionEnd);
116
129
  if (matchFunctionEnd !== null) {
117
130
  if (functionDef === null) {
118
- throw new BareScriptParserError('No matching function definition', line, 1, startLineNumber + ixLine);
131
+ throw new BareScriptParserError('No matching function definition', line, 1, startLineNumber + ixLine, scriptName);
119
132
  }
120
133
 
121
134
  // Check for un-matched label definitions
@@ -123,7 +136,7 @@ export function parseScript(scriptText, startLineNumber = 1) {
123
136
  const labelDef = labelDefs.pop();
124
137
  const [defKey] = Object.keys(labelDef);
125
138
  const def = labelDef[defKey];
126
- throw new BareScriptParserError(`Missing end${defKey} statement`, def.line, 1, def.lineNumber);
139
+ throw new BareScriptParserError(`Missing end${defKey} statement`, def.line, 1, def.lineNumber, scriptName);
127
140
  }
128
141
 
129
142
  functionDef = null;
@@ -138,7 +151,8 @@ export function parseScript(scriptText, startLineNumber = 1) {
138
151
  const ifthen = {
139
152
  'jump': {
140
153
  'label': `__bareScriptIf${labelIndex}`,
141
- 'expr': {'unary': {'op': '!', 'expr': parseExpression(matchIfBegin.groups.expr)}}
154
+ 'expr': {'unary': {'op': '!', 'expr': parseExpression(matchIfBegin.groups.expr, lineNumber, scriptName)}},
155
+ ...statementBase
142
156
  },
143
157
  'done': `__bareScriptDone${labelIndex}`,
144
158
  'hasElse': false,
@@ -160,26 +174,27 @@ export function parseScript(scriptText, startLineNumber = 1) {
160
174
  const labelDefDepth = (functionDef !== null ? functionLabelDefDepth : 0);
161
175
  const ifthen = (labelDefs.length > labelDefDepth ? (labelDefs[labelDefs.length - 1].if ?? null) : null);
162
176
  if (ifthen === null) {
163
- throw new BareScriptParserError('No matching if statement', line, 1, startLineNumber + ixLine);
177
+ throw new BareScriptParserError('No matching if statement', line, 1, startLineNumber + ixLine, scriptName);
164
178
  }
165
179
 
166
180
  // Cannot come after the else-then statement
167
181
  if (ifthen.hasElse) {
168
- throw new BareScriptParserError('Elif statement following else statement', line, 1, startLineNumber + ixLine);
182
+ throw new BareScriptParserError('Elif statement following else statement', line, 1, startLineNumber + ixLine, scriptName);
169
183
  }
170
184
 
171
185
  // Generate the next if-then jump statement
172
186
  const prevLabel = ifthen.jump.label;
173
187
  ifthen.jump = {
174
188
  'label': `__bareScriptIf${labelIndex}`,
175
- 'expr': {'unary': {'op': '!', 'expr': parseExpression(matchIfElseIf.groups.expr)}}
189
+ 'expr': {'unary': {'op': '!', 'expr': parseExpression(matchIfElseIf.groups.expr, lineNumber, scriptName)}},
190
+ ...statementBase
176
191
  };
177
192
  labelIndex += 1;
178
193
 
179
194
  // Add the if-then else statements
180
195
  statements.push(
181
- {'jump': {'label': ifthen.done}},
182
- {'label': prevLabel},
196
+ {'jump': {'label': ifthen.done, ...statementBase}},
197
+ {'label': {'name': prevLabel, ...statementBase}},
183
198
  {'jump': ifthen.jump}
184
199
  );
185
200
  continue;
@@ -192,19 +207,19 @@ export function parseScript(scriptText, startLineNumber = 1) {
192
207
  const labelDefDepth = (functionDef !== null ? functionLabelDefDepth : 0);
193
208
  const ifthen = (labelDefs.length > labelDefDepth ? (labelDefs[labelDefs.length - 1].if ?? null) : null);
194
209
  if (ifthen === null) {
195
- throw new BareScriptParserError('No matching if statement', line, 1, startLineNumber + ixLine);
210
+ throw new BareScriptParserError('No matching if statement', line, 1, startLineNumber + ixLine, scriptName);
196
211
  }
197
212
 
198
213
  // Cannot have multiple else-then statements
199
214
  if (ifthen.hasElse) {
200
- throw new BareScriptParserError('Multiple else statements', line, 1, startLineNumber + ixLine);
215
+ throw new BareScriptParserError('Multiple else statements', line, 1, startLineNumber + ixLine, scriptName);
201
216
  }
202
217
  ifthen.hasElse = true;
203
218
 
204
219
  // Add the if-then else statements
205
220
  statements.push(
206
- {'jump': {'label': ifthen.done}},
207
- {'label': ifthen.jump.label}
221
+ {'jump': {'label': ifthen.done, ...statementBase}},
222
+ {'label': {'name': ifthen.jump.label, ...statementBase}}
208
223
  );
209
224
  continue;
210
225
  }
@@ -216,7 +231,7 @@ export function parseScript(scriptText, startLineNumber = 1) {
216
231
  const labelDefDepth = (functionDef !== null ? functionLabelDefDepth : 0);
217
232
  const ifthen = (labelDefs.length > labelDefDepth ? (labelDefs.pop().if ?? null) : null);
218
233
  if (ifthen === null) {
219
- throw new BareScriptParserError('No matching if statement', line, 1, startLineNumber + ixLine);
234
+ throw new BareScriptParserError('No matching if statement', line, 1, startLineNumber + ixLine, scriptName);
220
235
  }
221
236
 
222
237
  // Update the previous jump statement's label, if necessary
@@ -225,7 +240,7 @@ export function parseScript(scriptText, startLineNumber = 1) {
225
240
  }
226
241
 
227
242
  // Add the if-then footer statement
228
- statements.push({'label': ifthen.done});
243
+ statements.push({'label': {'name': ifthen.done, ...statementBase}});
229
244
  continue;
230
245
  }
231
246
 
@@ -237,7 +252,7 @@ export function parseScript(scriptText, startLineNumber = 1) {
237
252
  'loop': `__bareScriptLoop${labelIndex}`,
238
253
  'continue': `__bareScriptLoop${labelIndex}`,
239
254
  'done': `__bareScriptDone${labelIndex}`,
240
- 'expr': parseExpression(matchWhileBegin.groups.expr),
255
+ 'expr': parseExpression(matchWhileBegin.groups.expr, lineNumber, scriptName),
241
256
  line,
242
257
  'lineNumber': startLineNumber + ixLine
243
258
  };
@@ -246,8 +261,8 @@ export function parseScript(scriptText, startLineNumber = 1) {
246
261
 
247
262
  // Add the while-do header statements
248
263
  statements.push(
249
- {'jump': {'label': whiledo.done, 'expr': {'unary': {'op': '!', 'expr': whiledo.expr}}}},
250
- {'label': whiledo.loop}
264
+ {'jump': {'label': whiledo.done, 'expr': {'unary': {'op': '!', 'expr': whiledo.expr}}, ...statementBase}},
265
+ {'label': {'name': whiledo.loop, ...statementBase}}
251
266
  );
252
267
  continue;
253
268
  }
@@ -259,13 +274,13 @@ export function parseScript(scriptText, startLineNumber = 1) {
259
274
  const labelDefDepth = (functionDef !== null ? functionLabelDefDepth : 0);
260
275
  const whiledo = (labelDefs.length > labelDefDepth ? (labelDefs.pop().while ?? null) : null);
261
276
  if (whiledo === null) {
262
- throw new BareScriptParserError('No matching while statement', line, 1, startLineNumber + ixLine);
277
+ throw new BareScriptParserError('No matching while statement', line, 1, startLineNumber + ixLine, scriptName);
263
278
  }
264
279
 
265
280
  // Add the while-do footer statements
266
281
  statements.push(
267
- {'jump': {'label': whiledo.loop, 'expr': whiledo.expr}},
268
- {'label': whiledo.done}
282
+ {'jump': {'label': whiledo.loop, 'expr': whiledo.expr, ...statementBase}},
283
+ {'label': {'name': whiledo.done, ...statementBase}}
269
284
  );
270
285
  continue;
271
286
  }
@@ -290,17 +305,23 @@ export function parseScript(scriptText, startLineNumber = 1) {
290
305
 
291
306
  // Add the for-each header statements
292
307
  statements.push(
293
- {'expr': {'name': foreach.values, 'expr': parseExpression(matchForBegin.groups.values)}},
308
+ {'expr': {
309
+ 'name': foreach.values,
310
+ 'expr': parseExpression(matchForBegin.groups.values, lineNumber, scriptName),
311
+ ...statementBase
312
+ }},
294
313
  {'expr': {
295
314
  'name': foreach.length,
296
- 'expr': {'function': {'name': 'arrayLength', 'args': [{'variable': foreach.values}]}}
315
+ 'expr': {'function': {'name': 'arrayLength', 'args': [{'variable': foreach.values}]}},
316
+ ...statementBase
297
317
  }},
298
- {'jump': {'label': foreach.done, 'expr': {'unary': {'op': '!', 'expr': {'variable': foreach.length}}}}},
299
- {'expr': {'name': foreach.index, 'expr': {'number': 0}}},
300
- {'label': foreach.loop},
318
+ {'jump': {'label': foreach.done, 'expr': {'unary': {'op': '!', 'expr': {'variable': foreach.length}}}, ...statementBase}},
319
+ {'expr': {'name': foreach.index, 'expr': {'number': 0}, ...statementBase}},
320
+ {'label': {'name': foreach.loop, ...statementBase}},
301
321
  {'expr': {
302
322
  'name': foreach.value,
303
- 'expr': {'function': {'name': 'arrayGet', 'args': [{'variable': foreach.values}, {'variable': foreach.index}]}}
323
+ 'expr': {'function': {'name': 'arrayGet', 'args': [{'variable': foreach.values}, {'variable': foreach.index}]}},
324
+ ...statementBase
304
325
  }}
305
326
  );
306
327
  continue;
@@ -313,23 +334,25 @@ export function parseScript(scriptText, startLineNumber = 1) {
313
334
  const labelDefDepth = (functionDef !== null ? functionLabelDefDepth : 0);
314
335
  const foreach = (labelDefs.length > labelDefDepth ? (labelDefs.pop().for ?? null) : null);
315
336
  if (foreach === null) {
316
- throw new BareScriptParserError('No matching for statement', line, 1, startLineNumber + ixLine);
337
+ throw new BareScriptParserError('No matching for statement', line, 1, startLineNumber + ixLine, scriptName);
317
338
  }
318
339
 
319
340
  // Add the for-each footer statements
320
341
  if (foreach.hasContinue) {
321
- statements.push({'label': foreach.continue});
342
+ statements.push({'label': {'name': foreach.continue, ...statementBase}});
322
343
  }
323
344
  statements.push(
324
345
  {'expr': {
325
346
  'name': foreach.index,
326
- 'expr': {'binary': {'op': '+', 'left': {'variable': foreach.index}, 'right': {'number': 1}}}
347
+ 'expr': {'binary': {'op': '+', 'left': {'variable': foreach.index}, 'right': {'number': 1}}},
348
+ ...statementBase
327
349
  }},
328
350
  {'jump': {
329
351
  'label': foreach.loop,
330
- 'expr': {'binary': {'op': '<', 'left': {'variable': foreach.index}, 'right': {'variable': foreach.length}}}
352
+ 'expr': {'binary': {'op': '<', 'left': {'variable': foreach.index}, 'right': {'variable': foreach.length}}},
353
+ ...statementBase
331
354
  }},
332
- {'label': foreach.done}
355
+ {'label': {'name': foreach.done, ...statementBase}}
333
356
  );
334
357
  continue;
335
358
  }
@@ -342,13 +365,13 @@ export function parseScript(scriptText, startLineNumber = 1) {
342
365
  const ixLabelDef = labelDefs.findLastIndex((def) => !('if' in def));
343
366
  const labelDef = (ixLabelDef >= labelDefDepth ? labelDefs[ixLabelDef] : null);
344
367
  if (labelDef === null) {
345
- throw new BareScriptParserError('Break statement outside of loop', line, 1, startLineNumber + ixLine);
368
+ throw new BareScriptParserError('Break statement outside of loop', line, 1, startLineNumber + ixLine, scriptName);
346
369
  }
347
370
  const [labelKey] = Object.keys(labelDef);
348
371
  const loopDef = labelDef[labelKey];
349
372
 
350
373
  // Add the break jump statement
351
- statements.push({'jump': {'label': loopDef.done}});
374
+ statements.push({'jump': {'label': loopDef.done, ...statementBase}});
352
375
  continue;
353
376
  }
354
377
 
@@ -360,34 +383,34 @@ export function parseScript(scriptText, startLineNumber = 1) {
360
383
  const ixLabelDef = labelDefs.findLastIndex((def) => !('if' in def));
361
384
  const labelDef = (ixLabelDef >= labelDefDepth ? labelDefs[ixLabelDef] : null);
362
385
  if (labelDef === null) {
363
- throw new BareScriptParserError('Continue statement outside of loop', line, 1, startLineNumber + ixLine);
386
+ throw new BareScriptParserError('Continue statement outside of loop', line, 1, startLineNumber + ixLine, scriptName);
364
387
  }
365
388
  const [labelKey] = Object.keys(labelDef);
366
389
  const loopDef = labelDef[labelKey];
367
390
 
368
391
  // Add the continue jump statement
369
392
  loopDef.hasContinue = true;
370
- statements.push({'jump': {'label': loopDef.continue}});
393
+ statements.push({'jump': {'label': loopDef.continue, ...statementBase}});
371
394
  continue;
372
395
  }
373
396
 
374
397
  // Label definition?
375
398
  const matchLabel = line.match(rScriptLabel);
376
399
  if (matchLabel !== null) {
377
- statements.push({'label': matchLabel.groups.name});
400
+ statements.push({'label': {'name': matchLabel.groups.name, ...statementBase}});
378
401
  continue;
379
402
  }
380
403
 
381
404
  // Jump definition?
382
405
  const matchJump = line.match(rScriptJump);
383
406
  if (matchJump !== null) {
384
- const jumpStatement = {'jump': {'label': matchJump.groups.name}};
407
+ const jumpStatement = {'jump': {'label': matchJump.groups.name, ...statementBase}};
385
408
  if (typeof matchJump.groups.expr !== 'undefined') {
386
409
  try {
387
- jumpStatement.jump.expr = parseExpression(matchJump.groups.expr);
410
+ jumpStatement.jump.expr = parseExpression(matchJump.groups.expr, lineNumber, scriptName);
388
411
  } catch (error) {
389
412
  const columnNumber = matchJump.groups.jump.length - matchJump.groups.expr.length - 1 + error.columnNumber;
390
- throw new BareScriptParserError(error.error, line, columnNumber, startLineNumber + ixLine);
413
+ throw new BareScriptParserError(error.error, line, columnNumber, startLineNumber + ixLine, scriptName);
391
414
  }
392
415
  }
393
416
  statements.push(jumpStatement);
@@ -397,13 +420,13 @@ export function parseScript(scriptText, startLineNumber = 1) {
397
420
  // Return definition?
398
421
  const matchReturn = line.match(rScriptReturn);
399
422
  if (matchReturn !== null) {
400
- const returnStatement = {'return': {}};
423
+ const returnStatement = {'return': {...statementBase}};
401
424
  if (typeof matchReturn.groups.expr !== 'undefined') {
402
425
  try {
403
- returnStatement.return.expr = parseExpression(matchReturn.groups.expr);
426
+ returnStatement.return.expr = parseExpression(matchReturn.groups.expr, lineNumber, scriptName);
404
427
  } catch (error) {
405
428
  const columnNumber = matchReturn.groups.return.length - matchReturn.groups.expr.length + error.columnNumber;
406
- throw new BareScriptParserError(error.error, line, columnNumber, startLineNumber + ixLine);
429
+ throw new BareScriptParserError(error.error, line, columnNumber, startLineNumber + ixLine, scriptName);
407
430
  }
408
431
  }
409
432
  statements.push(returnStatement);
@@ -417,8 +440,10 @@ export function parseScript(scriptText, startLineNumber = 1) {
417
440
  const url = (delim === '<' ? matchInclude.groups.url : matchInclude.groups.url.replace(rExprStringEscape, '$1'));
418
441
  let includeStatement = (statements.length ? statements[statements.length - 1] : null);
419
442
  if (includeStatement === null || !('include' in includeStatement)) {
420
- includeStatement = {'include': {'includes': []}};
443
+ includeStatement = {'include': {'includes': [], ...statementBase}};
421
444
  statements.push(includeStatement);
445
+ } else {
446
+ includeStatement.include.lineCount = (ixLinePart - includeStatement.include.lineNumber) + 2;
422
447
  }
423
448
  includeStatement.include.includes.push(delim === '<' ? {url, 'system': true} : {url});
424
449
  continue;
@@ -426,10 +451,10 @@ export function parseScript(scriptText, startLineNumber = 1) {
426
451
 
427
452
  // Expression
428
453
  try {
429
- const exprStatement = {'expr': {'expr': parseExpression(line)}};
454
+ const exprStatement = {'expr': {'expr': parseExpression(line, lineNumber, scriptName), ...statementBase}};
430
455
  statements.push(exprStatement);
431
456
  } catch (error) {
432
- throw new BareScriptParserError(error.error, line, error.columnNumber, startLineNumber + ixLine);
457
+ throw new BareScriptParserError(error.error, line, error.columnNumber, startLineNumber + ixLine, scriptName);
433
458
  }
434
459
  }
435
460
 
@@ -438,7 +463,7 @@ export function parseScript(scriptText, startLineNumber = 1) {
438
463
  const labelDef = labelDefs.pop();
439
464
  const [defKey] = Object.keys(labelDef);
440
465
  const def = labelDef[defKey];
441
- throw new BareScriptParserError(`Missing end${defKey} statement`, def.line, 1, def.lineNumber);
466
+ throw new BareScriptParserError(`Missing end${defKey} statement`, def.line, 1, def.lineNumber, scriptName);
442
467
  }
443
468
 
444
469
  return script;
@@ -483,22 +508,22 @@ const rScriptContinue = new RegExp(`^\\s*continue${rPartComment}`);
483
508
  * @returns {Object} The [expression model](./model/#var.vName='Expression')
484
509
  * @throws [BareScriptParserError]{@link module:lib/parser.BareScriptParserError}
485
510
  */
486
- export function parseExpression(exprText) {
511
+ export function parseExpression(exprText, lineNumber = null, scriptName = null) {
487
512
  try {
488
- const [expr, nextText] = parseBinaryExpression(exprText);
513
+ const [expr, nextText] = parseBinaryExpression(exprText, null);
489
514
  if (nextText.trim() !== '') {
490
- throw new BareScriptParserError('Syntax error', nextText);
515
+ throw new BareScriptParserError('Syntax error', nextText, 1, lineNumber, scriptName);
491
516
  }
492
517
  return expr;
493
518
  } catch (error) {
494
519
  const columnNumber = exprText.length - error.line.length + 1;
495
- throw new BareScriptParserError(error.error, exprText, columnNumber);
520
+ throw new BareScriptParserError(error.error, exprText, columnNumber, lineNumber, scriptName);
496
521
  }
497
522
  }
498
523
 
499
524
 
500
525
  // Helper function to parse a binary operator expression chain
501
- function parseBinaryExpression(exprText, binLeftExpr = null) {
526
+ function parseBinaryExpression(exprText, binLeftExpr) {
502
527
  // Parse the binary operator's left unary expression if none was passed
503
528
  let leftExpr;
504
529
  let binText;
@@ -575,10 +600,10 @@ function parseUnaryExpression(exprText) {
575
600
  const matchGroupOpen = exprText.match(rExprGroupOpen);
576
601
  if (matchGroupOpen !== null) {
577
602
  const groupText = exprText.slice(matchGroupOpen[0].length);
578
- const [expr, nextText] = parseBinaryExpression(groupText);
603
+ const [expr, nextText] = parseBinaryExpression(groupText, null);
579
604
  const matchGroupClose = nextText.match(rExprGroupClose);
580
605
  if (matchGroupClose === null) {
581
- throw new BareScriptParserError('Unmatched parenthesis', exprText);
606
+ throw new BareScriptParserError('Unmatched parenthesis', exprText, 1, null, null);
582
607
  }
583
608
  return [{'group': expr}, nextText.slice(matchGroupClose[0].length)];
584
609
  }
@@ -639,13 +664,13 @@ function parseUnaryExpression(exprText) {
639
664
  if (args.length !== 0) {
640
665
  const matchFunctionSeparator = argText.match(rExprFunctionSeparator);
641
666
  if (matchFunctionSeparator === null) {
642
- throw new BareScriptParserError('Syntax error', argText);
667
+ throw new BareScriptParserError('Syntax error', argText, 1, null, null);
643
668
  }
644
669
  argText = argText.slice(matchFunctionSeparator[0].length);
645
670
  }
646
671
 
647
672
  // Get the argument
648
- const [argExpr, nextArgText] = parseBinaryExpression(argText);
673
+ const [argExpr, nextArgText] = parseBinaryExpression(argText, null);
649
674
  args.push(argExpr);
650
675
  argText = nextArgText;
651
676
  }
@@ -674,7 +699,7 @@ function parseUnaryExpression(exprText) {
674
699
  return [expr, exprText.slice(matchVariableEx[0].length)];
675
700
  }
676
701
 
677
- throw new BareScriptParserError('Syntax error', exprText);
702
+ throw new BareScriptParserError('Syntax error', exprText, 1, null, null);
678
703
  }
679
704
 
680
705
 
@@ -705,6 +730,7 @@ const rExprVariableExEscape = /\\([\\\]])/g;
705
730
  * @property {string} line - The line text
706
731
  * @property {number} columnNumber - The error column number
707
732
  * @property {?number} lineNumber - The error line number
733
+ * @property {?string} scriptName - The error line number
708
734
  */
709
735
  export class BareScriptParserError extends Error {
710
736
  /**
@@ -712,11 +738,11 @@ export class BareScriptParserError extends Error {
712
738
  *
713
739
  * @param {string} error - The error description
714
740
  * @param {string} line - The line text
715
- * @param {number} [columnNumber=1] - The error column number
716
- * @param {?number} [lineNumber=null] - The error line number
717
- * @param {?string} [prefix=null] - The error message prefix line
741
+ * @param {number} [columnNumber] - The error column number
742
+ * @param {?number} [lineNumber] - The error line number
743
+ * @param {?string} [scriptName] - The script name
718
744
  */
719
- constructor(error, line, columnNumber = 1, lineNumber = null, prefix = null) {
745
+ constructor(error, line, columnNumber, lineNumber, scriptName) {
720
746
  // Parser error constants
721
747
  const lineLengthMax = 120;
722
748
  const lineSuffix = ' ...';
@@ -740,8 +766,9 @@ export class BareScriptParserError extends Error {
740
766
  }
741
767
 
742
768
  // Format the message
769
+ const errorPrefix = (lineNumber ? `${scriptName || ''}:${lineNumber}: ` : '');
743
770
  const message = `\
744
- ${prefix !== null ? `${prefix}\n` : ''}${error}${lineNumber !== null ? `, line number ${lineNumber}` : ''}:
771
+ ${errorPrefix}${error}
745
772
  ${lineError}
746
773
  ${' '.repeat(lineColumn - 1)}^
747
774
  `;
@@ -751,5 +778,6 @@ ${' '.repeat(lineColumn - 1)}^
751
778
  this.line = line;
752
779
  this.columnNumber = columnNumber;
753
780
  this.lineNumber = lineNumber;
781
+ this.scriptName = scriptName;
754
782
  }
755
783
  }