@borgar/fx 4.7.1 → 4.9.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/dist/fx.d.ts +86 -1
- package/dist/fx.js +1 -1
- package/docs/API.md +171 -7
- package/docs/AST_format.md +45 -15
- package/lib/astTypes.js +96 -0
- package/lib/constants.js +3 -0
- package/lib/fixRanges.js +3 -2
- package/lib/lexer.js +51 -0
- package/lib/lexer.spec.js +63 -0
- package/lib/lexerParts.js +5 -0
- package/lib/parser.js +235 -33
- package/lib/parser.spec.js +380 -89
- package/lib/sr.js +5 -3
- package/lib/sr.spec.js +50 -0
- package/package.json +1 -1
package/lib/parser.spec.js
CHANGED
|
@@ -64,21 +64,21 @@ test('parse errors', t => {
|
|
|
64
64
|
});
|
|
65
65
|
|
|
66
66
|
test('parse ranges', t => {
|
|
67
|
-
t.isParsed('A1', { type: 'ReferenceIdentifier', value: 'A1' });
|
|
68
|
-
t.isParsed('A1:B2', { type: 'ReferenceIdentifier', value: 'A1:B2' });
|
|
69
|
-
t.isParsed('A:B', { type: 'ReferenceIdentifier', value: 'A:B' });
|
|
70
|
-
t.isParsed('1:2', { type: 'ReferenceIdentifier', value: '1:2' });
|
|
71
|
-
t.isParsed('A1:2', { type: 'ReferenceIdentifier', value: 'A1:2' });
|
|
72
|
-
t.isParsed('1:A2', { type: 'ReferenceIdentifier', value: '1:A2' });
|
|
73
|
-
t.isParsed('Sheet!A1', { type: 'ReferenceIdentifier', value: 'Sheet!A1' });
|
|
74
|
-
t.isParsed('[Workbook]Sheet!A1', { type: 'ReferenceIdentifier', value: '[Workbook]Sheet!A1' });
|
|
75
|
-
t.isParsed('\'Sheet\'!A1', { type: 'ReferenceIdentifier', value: '\'Sheet\'!A1' });
|
|
76
|
-
t.isParsed('\'[Workbook]Sheet\'!A1', { type: 'ReferenceIdentifier', value: '\'[Workbook]Sheet\'!A1' });
|
|
77
|
-
t.isParsed('foo', { type: 'ReferenceIdentifier', value: 'foo' });
|
|
78
|
-
t.isParsed('Workbook!foo', { type: 'ReferenceIdentifier', value: 'Workbook!foo' });
|
|
79
|
-
t.isParsed('[Workbook]Sheet!foo', { type: 'ReferenceIdentifier', value: '[Workbook]Sheet!foo' });
|
|
80
|
-
t.isParsed('\'Workbook\'!A1', { type: 'ReferenceIdentifier', value: '\'Workbook\'!A1' });
|
|
81
|
-
t.isParsed('\'[Workbook]Sheet\'!A1', { type: 'ReferenceIdentifier', value: '\'[Workbook]Sheet\'!A1' });
|
|
67
|
+
t.isParsed('A1', { type: 'ReferenceIdentifier', value: 'A1', kind: 'range' });
|
|
68
|
+
t.isParsed('A1:B2', { type: 'ReferenceIdentifier', value: 'A1:B2', kind: 'range' });
|
|
69
|
+
t.isParsed('A:B', { type: 'ReferenceIdentifier', value: 'A:B', kind: 'beam' });
|
|
70
|
+
t.isParsed('1:2', { type: 'ReferenceIdentifier', value: '1:2', kind: 'beam' });
|
|
71
|
+
t.isParsed('A1:2', { type: 'ReferenceIdentifier', value: 'A1:2', kind: 'range' });
|
|
72
|
+
t.isParsed('1:A2', { type: 'ReferenceIdentifier', value: '1:A2', kind: 'range' });
|
|
73
|
+
t.isParsed('Sheet!A1', { type: 'ReferenceIdentifier', value: 'Sheet!A1', kind: 'range' });
|
|
74
|
+
t.isParsed('[Workbook]Sheet!A1', { type: 'ReferenceIdentifier', value: '[Workbook]Sheet!A1', kind: 'range' });
|
|
75
|
+
t.isParsed('\'Sheet\'!A1', { type: 'ReferenceIdentifier', value: '\'Sheet\'!A1', kind: 'range' });
|
|
76
|
+
t.isParsed('\'[Workbook]Sheet\'!A1', { type: 'ReferenceIdentifier', value: '\'[Workbook]Sheet\'!A1', kind: 'range' });
|
|
77
|
+
t.isParsed('foo', { type: 'ReferenceIdentifier', value: 'foo', kind: 'name' });
|
|
78
|
+
t.isParsed('Workbook!foo', { type: 'ReferenceIdentifier', value: 'Workbook!foo', kind: 'name' });
|
|
79
|
+
t.isParsed('[Workbook]Sheet!foo', { type: 'ReferenceIdentifier', value: '[Workbook]Sheet!foo', kind: 'name' });
|
|
80
|
+
t.isParsed('\'Workbook\'!A1', { type: 'ReferenceIdentifier', value: '\'Workbook\'!A1', kind: 'range' });
|
|
81
|
+
t.isParsed('\'[Workbook]Sheet\'!A1', { type: 'ReferenceIdentifier', value: '\'[Workbook]Sheet\'!A1', kind: 'range' });
|
|
82
82
|
t.end();
|
|
83
83
|
});
|
|
84
84
|
|
|
@@ -168,10 +168,10 @@ test('parse array literals', t => {
|
|
|
168
168
|
t.isParsed('{A1,A1:B2;A:A}', {
|
|
169
169
|
type: 'ArrayExpression',
|
|
170
170
|
elements: [ [
|
|
171
|
-
{ type: 'ReferenceIdentifier', value: 'A1' },
|
|
172
|
-
{ type: 'ReferenceIdentifier', value: 'A1:B2' }
|
|
171
|
+
{ type: 'ReferenceIdentifier', value: 'A1', kind: 'range' },
|
|
172
|
+
{ type: 'ReferenceIdentifier', value: 'A1:B2', kind: 'range' }
|
|
173
173
|
], [
|
|
174
|
-
{ type: 'ReferenceIdentifier', value: 'A:A' }
|
|
174
|
+
{ type: 'ReferenceIdentifier', value: 'A:A', kind: 'beam' }
|
|
175
175
|
] ]
|
|
176
176
|
}, { permitArrayRanges: true });
|
|
177
177
|
t.isParsed('{-0.1,"foo";#NAME?,false}', {
|
|
@@ -202,8 +202,6 @@ test('parse array literals', t => {
|
|
|
202
202
|
// ] ]
|
|
203
203
|
// }, { negativeNumbers: false });
|
|
204
204
|
t.isInvalidExpr('{A1}', { permitArrayRanges: false });
|
|
205
|
-
// TODO: WHY???
|
|
206
|
-
// t.isInvalidExpr('{-1}', { negativeNumbers: true });
|
|
207
205
|
t.isInvalidExpr('{--1}', { negativeNumbers: true });
|
|
208
206
|
t.isInvalidExpr('{--1}', { negativeNumbers: false });
|
|
209
207
|
t.isInvalidExpr('{---1}', { negativeNumbers: true });
|
|
@@ -226,7 +224,7 @@ test('parse array literals', t => {
|
|
|
226
224
|
{ type: 'ArrayExpression', elements: [
|
|
227
225
|
[ { type: 'Literal', value: 1234, raw: '1234' } ],
|
|
228
226
|
[ { type: 'CallExpression', callee: { type: 'Identifier', name: 'UNIQUE' }, arguments: [
|
|
229
|
-
{ type: 'ReferenceIdentifier', value: 'A:A' }
|
|
227
|
+
{ type: 'ReferenceIdentifier', value: 'A:A', kind: 'beam' }
|
|
230
228
|
] } ]
|
|
231
229
|
] },
|
|
232
230
|
{ permitArrayCalls: true });
|
|
@@ -273,16 +271,16 @@ test('parse function calls', t => {
|
|
|
273
271
|
t.isParsed('=FOO(A1,B2)', {
|
|
274
272
|
type: 'CallExpression', callee: { type: 'Identifier', name: 'FOO' },
|
|
275
273
|
arguments: [
|
|
276
|
-
{ type: 'ReferenceIdentifier', value: 'A1' },
|
|
277
|
-
{ type: 'ReferenceIdentifier', value: 'B2' }
|
|
274
|
+
{ type: 'ReferenceIdentifier', value: 'A1', kind: 'range' },
|
|
275
|
+
{ type: 'ReferenceIdentifier', value: 'B2', kind: 'range' }
|
|
278
276
|
]
|
|
279
277
|
});
|
|
280
278
|
t.isParsed('=FOO((A1,B2))', {
|
|
281
279
|
type: 'CallExpression', callee: { type: 'Identifier', name: 'FOO' },
|
|
282
280
|
arguments: [
|
|
283
281
|
{ type: 'BinaryExpression', operator: ',', arguments: [
|
|
284
|
-
{ type: 'ReferenceIdentifier', value: 'A1' },
|
|
285
|
-
{ type: 'ReferenceIdentifier', value: 'B2' }
|
|
282
|
+
{ type: 'ReferenceIdentifier', value: 'A1', kind: 'range' },
|
|
283
|
+
{ type: 'ReferenceIdentifier', value: 'B2', kind: 'range' }
|
|
286
284
|
] }
|
|
287
285
|
]
|
|
288
286
|
});
|
|
@@ -326,7 +324,7 @@ test('parse function calls', t => {
|
|
|
326
324
|
test('parse unary operator %', t => {
|
|
327
325
|
t.isParsed('A1%', {
|
|
328
326
|
type: 'UnaryExpression', operator: '%',
|
|
329
|
-
arguments: [ { type: 'ReferenceIdentifier', value: 'A1' } ]
|
|
327
|
+
arguments: [ { type: 'ReferenceIdentifier', value: 'A1', kind: 'range' } ]
|
|
330
328
|
});
|
|
331
329
|
t.isParsed('1%', {
|
|
332
330
|
type: 'UnaryExpression', operator: '%',
|
|
@@ -352,7 +350,7 @@ test('parse unary operator -', t => {
|
|
|
352
350
|
});
|
|
353
351
|
t.isParsed('-A1:B2', {
|
|
354
352
|
type: 'UnaryExpression', operator: '-',
|
|
355
|
-
arguments: [ { type: 'ReferenceIdentifier', value: 'A1:B2' } ]
|
|
353
|
+
arguments: [ { type: 'ReferenceIdentifier', value: 'A1:B2', kind: 'range' } ]
|
|
356
354
|
});
|
|
357
355
|
t.isParsed('--1', {
|
|
358
356
|
type: 'UnaryExpression', operator: '-',
|
|
@@ -385,7 +383,7 @@ test('parse unary operator +', t => {
|
|
|
385
383
|
});
|
|
386
384
|
t.isParsed('+A1:B2', {
|
|
387
385
|
type: 'UnaryExpression', operator: '+',
|
|
388
|
-
arguments: [ { type: 'ReferenceIdentifier', value: 'A1:B2' } ]
|
|
386
|
+
arguments: [ { type: 'ReferenceIdentifier', value: 'A1:B2', kind: 'range' } ]
|
|
389
387
|
});
|
|
390
388
|
t.isInvalidExpr('++');
|
|
391
389
|
t.isInvalidExpr('+');
|
|
@@ -395,19 +393,19 @@ test('parse unary operator +', t => {
|
|
|
395
393
|
test('parse unary operator #', t => {
|
|
396
394
|
t.isParsed('D9#', {
|
|
397
395
|
type: 'UnaryExpression', operator: '#',
|
|
398
|
-
arguments: [ { type: 'ReferenceIdentifier', value: 'D9' } ]
|
|
396
|
+
arguments: [ { type: 'ReferenceIdentifier', value: 'D9', kind: 'range' } ]
|
|
399
397
|
});
|
|
400
398
|
t.isParsed('A1:B2#', { // this parses but is a runtime error in Excel
|
|
401
399
|
type: 'UnaryExpression', operator: '#',
|
|
402
|
-
arguments: [ { type: 'ReferenceIdentifier', value: 'A1:B2' } ]
|
|
400
|
+
arguments: [ { type: 'ReferenceIdentifier', value: 'A1:B2', kind: 'range' } ]
|
|
403
401
|
});
|
|
404
402
|
t.isParsed('(A1):(B2)#', { // this parses but is a runtime error in Excel
|
|
405
403
|
type: 'UnaryExpression', operator: '#',
|
|
406
404
|
arguments: [ {
|
|
407
405
|
type: 'BinaryExpression', operator: ':',
|
|
408
406
|
arguments: [
|
|
409
|
-
{ type: 'ReferenceIdentifier', value: 'A1' },
|
|
410
|
-
{ type: 'ReferenceIdentifier', value: 'B2' }
|
|
407
|
+
{ type: 'ReferenceIdentifier', value: 'A1', kind: 'range' },
|
|
408
|
+
{ type: 'ReferenceIdentifier', value: 'B2', kind: 'range' }
|
|
411
409
|
] } ]
|
|
412
410
|
});
|
|
413
411
|
t.isParsed('(A1,B2)#', {
|
|
@@ -415,8 +413,8 @@ test('parse unary operator #', t => {
|
|
|
415
413
|
arguments: [ {
|
|
416
414
|
type: 'BinaryExpression', operator: ',',
|
|
417
415
|
arguments: [
|
|
418
|
-
{ type: 'ReferenceIdentifier', value: 'A1' },
|
|
419
|
-
{ type: 'ReferenceIdentifier', value: 'B2' }
|
|
416
|
+
{ type: 'ReferenceIdentifier', value: 'A1', kind: 'range' },
|
|
417
|
+
{ type: 'ReferenceIdentifier', value: 'B2', kind: 'range' }
|
|
420
418
|
] } ]
|
|
421
419
|
});
|
|
422
420
|
t.isParsed('(A1 B2)#', {
|
|
@@ -424,8 +422,8 @@ test('parse unary operator #', t => {
|
|
|
424
422
|
arguments: [ {
|
|
425
423
|
type: 'BinaryExpression', operator: ' ',
|
|
426
424
|
arguments: [
|
|
427
|
-
{ type: 'ReferenceIdentifier', value: 'A1' },
|
|
428
|
-
{ type: 'ReferenceIdentifier', value: 'B2' }
|
|
425
|
+
{ type: 'ReferenceIdentifier', value: 'A1', kind: 'range' },
|
|
426
|
+
{ type: 'ReferenceIdentifier', value: 'B2', kind: 'range' }
|
|
429
427
|
] } ]
|
|
430
428
|
});
|
|
431
429
|
t.isParsed('#REF!#', {
|
|
@@ -461,11 +459,11 @@ test('parse unary operator @', t => {
|
|
|
461
459
|
});
|
|
462
460
|
t.isParsed('@D9', {
|
|
463
461
|
type: 'UnaryExpression', operator: '@',
|
|
464
|
-
arguments: [ { type: 'ReferenceIdentifier', value: 'D9' } ]
|
|
462
|
+
arguments: [ { type: 'ReferenceIdentifier', value: 'D9', kind: 'range' } ]
|
|
465
463
|
});
|
|
466
464
|
t.isParsed('@A1:B2', {
|
|
467
465
|
type: 'UnaryExpression', operator: '@',
|
|
468
|
-
arguments: [ { type: 'ReferenceIdentifier', value: 'A1:B2' } ]
|
|
466
|
+
arguments: [ { type: 'ReferenceIdentifier', value: 'A1:B2', kind: 'range' } ]
|
|
469
467
|
});
|
|
470
468
|
t.isParsed('@#REF!', {
|
|
471
469
|
type: 'UnaryExpression', operator: '@',
|
|
@@ -573,26 +571,26 @@ test('parse unary operator @', t => {
|
|
|
573
571
|
t.isParsed(`named1${op}named2`, {
|
|
574
572
|
type: 'BinaryExpression', operator: op,
|
|
575
573
|
arguments: [
|
|
576
|
-
{ type: 'ReferenceIdentifier', value: 'named1' },
|
|
577
|
-
{ type: 'ReferenceIdentifier', value: 'named2' }
|
|
574
|
+
{ type: 'ReferenceIdentifier', value: 'named1', kind: 'name' },
|
|
575
|
+
{ type: 'ReferenceIdentifier', value: 'named2', kind: 'name' }
|
|
578
576
|
] });
|
|
579
577
|
t.isParsed(`A1${op}named2`, {
|
|
580
578
|
type: 'BinaryExpression', operator: op,
|
|
581
579
|
arguments: [
|
|
582
|
-
{ type: 'ReferenceIdentifier', value: 'A1' },
|
|
583
|
-
{ type: 'ReferenceIdentifier', value: 'named2' }
|
|
580
|
+
{ type: 'ReferenceIdentifier', value: 'A1', kind: 'range' },
|
|
581
|
+
{ type: 'ReferenceIdentifier', value: 'named2', kind: 'name' }
|
|
584
582
|
] });
|
|
585
583
|
t.isParsed(`named1${op}B2`, {
|
|
586
584
|
type: 'BinaryExpression', operator: op,
|
|
587
585
|
arguments: [
|
|
588
|
-
{ type: 'ReferenceIdentifier', value: 'named1' },
|
|
589
|
-
{ type: 'ReferenceIdentifier', value: 'B2' }
|
|
586
|
+
{ type: 'ReferenceIdentifier', value: 'named1', kind: 'name' },
|
|
587
|
+
{ type: 'ReferenceIdentifier', value: 'B2', kind: 'range' }
|
|
590
588
|
] });
|
|
591
589
|
t.isParsed(`(A1)${op}(B2)`, {
|
|
592
590
|
type: 'BinaryExpression', operator: op,
|
|
593
591
|
arguments: [
|
|
594
|
-
{ type: 'ReferenceIdentifier', value: 'A1' },
|
|
595
|
-
{ type: 'ReferenceIdentifier', value: 'B2' }
|
|
592
|
+
{ type: 'ReferenceIdentifier', value: 'A1', kind: 'range' },
|
|
593
|
+
{ type: 'ReferenceIdentifier', value: 'B2', kind: 'range' }
|
|
596
594
|
] });
|
|
597
595
|
t.isInvalidExpr(`A1${op}0`);
|
|
598
596
|
t.isInvalidExpr(`0${op}A1`);
|
|
@@ -603,14 +601,14 @@ test('parse unary operator @', t => {
|
|
|
603
601
|
t.isParsed(`A1${op}#REF!`, {
|
|
604
602
|
type: 'BinaryExpression', operator: op,
|
|
605
603
|
arguments: [
|
|
606
|
-
{ type: 'ReferenceIdentifier', value: 'A1' },
|
|
604
|
+
{ type: 'ReferenceIdentifier', value: 'A1', kind: 'range' },
|
|
607
605
|
{ type: 'ErrorLiteral', value: '#REF!', raw: '#REF!' }
|
|
608
606
|
] });
|
|
609
607
|
t.isParsed(`#REF!${op}B2`, {
|
|
610
608
|
type: 'BinaryExpression', operator: op,
|
|
611
609
|
arguments: [
|
|
612
610
|
{ type: 'ErrorLiteral', value: '#REF!', raw: '#REF!' },
|
|
613
|
-
{ type: 'ReferenceIdentifier', value: 'B2' }
|
|
611
|
+
{ type: 'ReferenceIdentifier', value: 'B2', kind: 'range' }
|
|
614
612
|
] });
|
|
615
613
|
t.isInvalidExpr(`A1${op}#NAME?`);
|
|
616
614
|
t.isInvalidExpr(`A1${op}#VALUE!`);
|
|
@@ -622,19 +620,19 @@ test('parse unary operator @', t => {
|
|
|
622
620
|
arguments: [
|
|
623
621
|
{ type: 'BinaryExpression', operator: ',',
|
|
624
622
|
arguments: [
|
|
625
|
-
{ type: 'ReferenceIdentifier', value: 'A1' },
|
|
626
|
-
{ type: 'ReferenceIdentifier', value: 'B2' }
|
|
623
|
+
{ type: 'ReferenceIdentifier', value: 'A1', kind: 'range' },
|
|
624
|
+
{ type: 'ReferenceIdentifier', value: 'B2', kind: 'range' }
|
|
627
625
|
] },
|
|
628
|
-
{ type: 'ReferenceIdentifier', value: 'C3' }
|
|
626
|
+
{ type: 'ReferenceIdentifier', value: 'C3', kind: 'range' }
|
|
629
627
|
] });
|
|
630
628
|
t.isParsed(`C3${op}(A1,B2)`, {
|
|
631
629
|
type: 'BinaryExpression', operator: op,
|
|
632
630
|
arguments: [
|
|
633
|
-
{ type: 'ReferenceIdentifier', value: 'C3' },
|
|
631
|
+
{ type: 'ReferenceIdentifier', value: 'C3', kind: 'range' },
|
|
634
632
|
{ type: 'BinaryExpression', operator: ',',
|
|
635
633
|
arguments: [
|
|
636
|
-
{ type: 'ReferenceIdentifier', value: 'A1' },
|
|
637
|
-
{ type: 'ReferenceIdentifier', value: 'B2' }
|
|
634
|
+
{ type: 'ReferenceIdentifier', value: 'A1', kind: 'range' },
|
|
635
|
+
{ type: 'ReferenceIdentifier', value: 'B2', kind: 'range' }
|
|
638
636
|
] }
|
|
639
637
|
] });
|
|
640
638
|
// intersection ops
|
|
@@ -643,19 +641,19 @@ test('parse unary operator @', t => {
|
|
|
643
641
|
arguments: [
|
|
644
642
|
{ type: 'BinaryExpression', operator: ' ',
|
|
645
643
|
arguments: [
|
|
646
|
-
{ type: 'ReferenceIdentifier', value: 'A1' },
|
|
647
|
-
{ type: 'ReferenceIdentifier', value: 'B2' }
|
|
644
|
+
{ type: 'ReferenceIdentifier', value: 'A1', kind: 'range' },
|
|
645
|
+
{ type: 'ReferenceIdentifier', value: 'B2', kind: 'range' }
|
|
648
646
|
] },
|
|
649
|
-
{ type: 'ReferenceIdentifier', value: 'C3' }
|
|
647
|
+
{ type: 'ReferenceIdentifier', value: 'C3', kind: 'range' }
|
|
650
648
|
] });
|
|
651
649
|
t.isParsed(`C3${op}(A1 B2)`, {
|
|
652
650
|
type: 'BinaryExpression', operator: op,
|
|
653
651
|
arguments: [
|
|
654
|
-
{ type: 'ReferenceIdentifier', value: 'C3' },
|
|
652
|
+
{ type: 'ReferenceIdentifier', value: 'C3', kind: 'range' },
|
|
655
653
|
{ type: 'BinaryExpression', operator: ' ',
|
|
656
654
|
arguments: [
|
|
657
|
-
{ type: 'ReferenceIdentifier', value: 'A1' },
|
|
658
|
-
{ type: 'ReferenceIdentifier', value: 'B2' }
|
|
655
|
+
{ type: 'ReferenceIdentifier', value: 'A1', kind: 'range' },
|
|
656
|
+
{ type: 'ReferenceIdentifier', value: 'B2', kind: 'range' }
|
|
659
657
|
] }
|
|
660
658
|
] });
|
|
661
659
|
// join ops
|
|
@@ -664,21 +662,27 @@ test('parse unary operator @', t => {
|
|
|
664
662
|
arguments: [
|
|
665
663
|
{ type: 'BinaryExpression', operator: ':',
|
|
666
664
|
arguments: [
|
|
667
|
-
{ type: 'ReferenceIdentifier', value: 'A1' },
|
|
668
|
-
{ type: 'ReferenceIdentifier', value: 'B2' }
|
|
665
|
+
{ type: 'ReferenceIdentifier', value: 'A1', kind: 'range' },
|
|
666
|
+
{ type: 'ReferenceIdentifier', value: 'B2', kind: 'range' }
|
|
669
667
|
] },
|
|
670
|
-
{ type: 'ReferenceIdentifier', value: 'C3' }
|
|
668
|
+
{ type: 'ReferenceIdentifier', value: 'C3', kind: 'range' }
|
|
671
669
|
] });
|
|
672
670
|
t.isParsed(`C3${op}(A1:(B2))`, {
|
|
673
671
|
type: 'BinaryExpression', operator: op,
|
|
674
672
|
arguments: [
|
|
675
|
-
{ type: 'ReferenceIdentifier', value: 'C3' },
|
|
673
|
+
{ type: 'ReferenceIdentifier', value: 'C3', kind: 'range' },
|
|
676
674
|
{ type: 'BinaryExpression', operator: ':',
|
|
677
675
|
arguments: [
|
|
678
|
-
{ type: 'ReferenceIdentifier', value: 'A1' },
|
|
679
|
-
{ type: 'ReferenceIdentifier', value: 'B2' }
|
|
676
|
+
{ type: 'ReferenceIdentifier', value: 'A1', kind: 'range' },
|
|
677
|
+
{ type: 'ReferenceIdentifier', value: 'B2', kind: 'range' }
|
|
680
678
|
] }
|
|
681
679
|
] });
|
|
680
|
+
t.isParsed(`A1 ${op} B2`, {
|
|
681
|
+
type: 'BinaryExpression', operator: op,
|
|
682
|
+
arguments: [
|
|
683
|
+
{ type: 'ReferenceIdentifier', value: 'A1', kind: 'range' },
|
|
684
|
+
{ type: 'ReferenceIdentifier', value: 'B2', kind: 'range' }
|
|
685
|
+
] });
|
|
682
686
|
// ref calls
|
|
683
687
|
([
|
|
684
688
|
[ 'ANCHORARRAY', true ],
|
|
@@ -688,8 +692,8 @@ test('parse unary operator @', t => {
|
|
|
688
692
|
[ 'IFS', true ],
|
|
689
693
|
[ 'INDEX', true ],
|
|
690
694
|
[ 'INDIRECT', true ],
|
|
691
|
-
[ 'LAMBDA', true ],
|
|
692
|
-
[ 'LET', true ],
|
|
695
|
+
// [ 'LAMBDA', true ],
|
|
696
|
+
// [ 'LET', true ],
|
|
693
697
|
[ 'OFFSET', true ],
|
|
694
698
|
[ 'REDUCE', true ],
|
|
695
699
|
[ 'SINGLE', true ],
|
|
@@ -708,12 +712,12 @@ test('parse unary operator @', t => {
|
|
|
708
712
|
type: 'BinaryExpression', operator: op,
|
|
709
713
|
arguments: [
|
|
710
714
|
{ type: 'CallExpression', callee: { type: 'Identifier', name: funcName }, arguments: [] },
|
|
711
|
-
{ type: 'ReferenceIdentifier', value: 'C3' }
|
|
715
|
+
{ type: 'ReferenceIdentifier', value: 'C3', kind: 'range' }
|
|
712
716
|
] });
|
|
713
717
|
t.isParsed(`C3${op}${funcName}()`, {
|
|
714
718
|
type: 'BinaryExpression', operator: op,
|
|
715
719
|
arguments: [
|
|
716
|
-
{ type: 'ReferenceIdentifier', value: 'C3' },
|
|
720
|
+
{ type: 'ReferenceIdentifier', value: 'C3', kind: 'range' },
|
|
717
721
|
{ type: 'CallExpression', callee: { type: 'Identifier', name: funcName }, arguments: [] }
|
|
718
722
|
] });
|
|
719
723
|
}
|
|
@@ -731,15 +735,15 @@ test('union operators are normalized', t => {
|
|
|
731
735
|
t.isParsed('A1 B2', {
|
|
732
736
|
type: 'BinaryExpression', operator: ' ',
|
|
733
737
|
arguments: [
|
|
734
|
-
{ type: 'ReferenceIdentifier', value: 'A1' },
|
|
735
|
-
{ type: 'ReferenceIdentifier', value: 'B2' }
|
|
738
|
+
{ type: 'ReferenceIdentifier', value: 'A1', kind: 'range' },
|
|
739
|
+
{ type: 'ReferenceIdentifier', value: 'B2', kind: 'range' }
|
|
736
740
|
]
|
|
737
741
|
});
|
|
738
742
|
t.isParsed('A1 B2', {
|
|
739
743
|
type: 'BinaryExpression', operator: ' ',
|
|
740
744
|
arguments: [
|
|
741
|
-
{ type: 'ReferenceIdentifier', value: 'A1' },
|
|
742
|
-
{ type: 'ReferenceIdentifier', value: 'B2' }
|
|
745
|
+
{ type: 'ReferenceIdentifier', value: 'A1', kind: 'range' },
|
|
746
|
+
{ type: 'ReferenceIdentifier', value: 'B2', kind: 'range' }
|
|
743
747
|
]
|
|
744
748
|
});
|
|
745
749
|
t.end();
|
|
@@ -768,7 +772,7 @@ test('position information is correct', t => {
|
|
|
768
772
|
);
|
|
769
773
|
t.isParsed(
|
|
770
774
|
'=Sheet1!A1:B2',
|
|
771
|
-
{ type: 'ReferenceIdentifier', value: 'Sheet1!A1:B2', loc: [ 1, 13 ] },
|
|
775
|
+
{ type: 'ReferenceIdentifier', value: 'Sheet1!A1:B2', kind: 'range', loc: [ 1, 13 ] },
|
|
772
776
|
{ withLocation: true }
|
|
773
777
|
);
|
|
774
778
|
t.isParsed(
|
|
@@ -780,7 +784,7 @@ test('position information is correct', t => {
|
|
|
780
784
|
t.isParsed(
|
|
781
785
|
'=-A1',
|
|
782
786
|
{ type: 'UnaryExpression', loc: [ 1, 4 ], operator: '-', arguments: [
|
|
783
|
-
{ type: 'ReferenceIdentifier', value: 'A1', loc: [ 2, 4 ] }
|
|
787
|
+
{ type: 'ReferenceIdentifier', value: 'A1', kind: 'range', loc: [ 2, 4 ] }
|
|
784
788
|
] },
|
|
785
789
|
{ withLocation: true }
|
|
786
790
|
);
|
|
@@ -809,8 +813,8 @@ test('position information is correct', t => {
|
|
|
809
813
|
t.isParsed(
|
|
810
814
|
'=(A1 B2)',
|
|
811
815
|
{ type: 'BinaryExpression', loc: [ 2, 7 ], operator: ' ', arguments: [
|
|
812
|
-
{ type: 'ReferenceIdentifier', value: 'A1', loc: [ 2, 4 ] },
|
|
813
|
-
{ type: 'ReferenceIdentifier', value: 'B2', loc: [ 5, 7 ] }
|
|
816
|
+
{ type: 'ReferenceIdentifier', value: 'A1', kind: 'range', loc: [ 2, 4 ] },
|
|
817
|
+
{ type: 'ReferenceIdentifier', value: 'B2', kind: 'range', loc: [ 5, 7 ] }
|
|
814
818
|
] },
|
|
815
819
|
{ withLocation: true }
|
|
816
820
|
);
|
|
@@ -844,20 +848,20 @@ test('does not tolerate unterminated tokens', t => {
|
|
|
844
848
|
{ type: 'CallExpression', callee: { type: 'Identifier', name: 'SORT' },
|
|
845
849
|
arguments: [
|
|
846
850
|
{ type: 'ArrayExpression', elements: [
|
|
847
|
-
[ { type: 'ReferenceIdentifier', value: 'A:A' },
|
|
848
|
-
{ type: 'ReferenceIdentifier', value: 'B:B' } ]
|
|
851
|
+
[ { type: 'ReferenceIdentifier', value: 'A:A', kind: 'beam' },
|
|
852
|
+
{ type: 'ReferenceIdentifier', value: 'B:B', kind: 'beam' } ]
|
|
849
853
|
] }
|
|
850
854
|
] },
|
|
851
855
|
{ permitArrayRanges: true });
|
|
852
856
|
// whitespace in arguments
|
|
853
857
|
t.isParsed('=A2:A5=XLOOKUP(B1,C:C, D:D)',
|
|
854
858
|
{ type: 'BinaryExpression', operator: '=', arguments: [
|
|
855
|
-
{ type: 'ReferenceIdentifier', value: 'A2:A5' },
|
|
859
|
+
{ type: 'ReferenceIdentifier', value: 'A2:A5', kind: 'range' },
|
|
856
860
|
{ type: 'CallExpression', callee: { type: 'Identifier', name: 'XLOOKUP' },
|
|
857
861
|
arguments: [
|
|
858
|
-
{ type: 'ReferenceIdentifier', value: 'B1' },
|
|
859
|
-
{ type: 'ReferenceIdentifier', value: 'C:C' },
|
|
860
|
-
{ type: 'ReferenceIdentifier', value: 'D:D' }
|
|
862
|
+
{ type: 'ReferenceIdentifier', value: 'B1', kind: 'range' },
|
|
863
|
+
{ type: 'ReferenceIdentifier', value: 'C:C', kind: 'beam' },
|
|
864
|
+
{ type: 'ReferenceIdentifier', value: 'D:D', kind: 'beam' }
|
|
861
865
|
] }
|
|
862
866
|
] },
|
|
863
867
|
{ permitArrayRanges: true });
|
|
@@ -865,14 +869,14 @@ test('does not tolerate unterminated tokens', t => {
|
|
|
865
869
|
t.isParsed('=SUM(12 , B:B)',
|
|
866
870
|
{ type: 'CallExpression', callee: { type: 'Identifier', name: 'SUM' }, arguments: [
|
|
867
871
|
{ type: 'Literal', value: 12, raw: '12' },
|
|
868
|
-
{ type: 'ReferenceIdentifier', value: 'B:B' }
|
|
872
|
+
{ type: 'ReferenceIdentifier', value: 'B:B', kind: 'beam' }
|
|
869
873
|
] },
|
|
870
874
|
{ permitArrayCalls: true });
|
|
871
875
|
// whitespace tailing operator
|
|
872
876
|
t.isParsed('=A:A= C1',
|
|
873
877
|
{ type: 'BinaryExpression', operator: '=', arguments: [
|
|
874
|
-
{ type: 'ReferenceIdentifier', value: 'A:A' },
|
|
875
|
-
{ type: 'ReferenceIdentifier', value: 'C1' }
|
|
878
|
+
{ type: 'ReferenceIdentifier', value: 'A:A', kind: 'beam' },
|
|
879
|
+
{ type: 'ReferenceIdentifier', value: 'C1', kind: 'range' }
|
|
876
880
|
] },
|
|
877
881
|
{ permitArrayCalls: true });
|
|
878
882
|
t.end();
|
|
@@ -883,10 +887,297 @@ test('parser can permit xlsx mode references', t => {
|
|
|
883
887
|
t.isParsed('=SUM([Workbook.xlsx]!A1+[Workbook.xlsx]!Table1[#Data])',
|
|
884
888
|
{ type: 'CallExpression', callee: { type: 'Identifier', name: 'SUM' }, arguments: [
|
|
885
889
|
{ type: 'BinaryExpression', operator: '+', arguments: [
|
|
886
|
-
{ type: 'ReferenceIdentifier', value: '[Workbook.xlsx]!A1' },
|
|
887
|
-
{ type: 'ReferenceIdentifier', value: '[Workbook.xlsx]!Table1[#Data]' }
|
|
890
|
+
{ type: 'ReferenceIdentifier', value: '[Workbook.xlsx]!A1', kind: 'range' },
|
|
891
|
+
{ type: 'ReferenceIdentifier', value: '[Workbook.xlsx]!Table1[#Data]', kind: 'table' }
|
|
888
892
|
] }
|
|
889
893
|
] },
|
|
890
894
|
{ xlsx: true });
|
|
891
895
|
t.end();
|
|
892
896
|
});
|
|
897
|
+
|
|
898
|
+
test('parser supports LAMBDA expressions', t => {
|
|
899
|
+
t.isInvalidExpr('LAMBDA(,)');
|
|
900
|
+
t.isInvalidExpr('LAMBDA(a,)');
|
|
901
|
+
t.isInvalidExpr('LAMBDA(a,,)');
|
|
902
|
+
t.isInvalidExpr('=LAMBDA(1,1)');
|
|
903
|
+
t.isInvalidExpr('=LAMBDA(a,1,a)');
|
|
904
|
+
t.isInvalidExpr('=LAMBDA(a,A,1)');
|
|
905
|
+
t.isInvalidExpr('=LAMBDA(a,a,1)');
|
|
906
|
+
t.isInvalidExpr('=LAMBDA(A1,B1,1)');
|
|
907
|
+
t.isParsed('=LAMBDA()', {
|
|
908
|
+
type: 'LambdaExpression',
|
|
909
|
+
params: [],
|
|
910
|
+
body: null
|
|
911
|
+
});
|
|
912
|
+
t.isParsed('=LAMBDA(1)', {
|
|
913
|
+
type: 'LambdaExpression',
|
|
914
|
+
params: [],
|
|
915
|
+
body: {
|
|
916
|
+
type: 'Literal',
|
|
917
|
+
value: 1,
|
|
918
|
+
raw: '1'
|
|
919
|
+
}
|
|
920
|
+
});
|
|
921
|
+
t.isParsed('=LAMBDA(1+1)', {
|
|
922
|
+
type: 'LambdaExpression',
|
|
923
|
+
params: [],
|
|
924
|
+
body: {
|
|
925
|
+
type: 'BinaryExpression',
|
|
926
|
+
operator: '+',
|
|
927
|
+
arguments: [
|
|
928
|
+
{ type: 'Literal', value: 1, raw: '1' },
|
|
929
|
+
{ type: 'Literal', value: 1, raw: '1' }
|
|
930
|
+
]
|
|
931
|
+
}
|
|
932
|
+
});
|
|
933
|
+
t.isParsed('=LAMBDA(a,1)', {
|
|
934
|
+
type: 'LambdaExpression',
|
|
935
|
+
body: { type: 'Literal', value: 1, raw: '1' },
|
|
936
|
+
params: [
|
|
937
|
+
{ type: 'Identifier', name: 'a' }
|
|
938
|
+
]
|
|
939
|
+
});
|
|
940
|
+
t.isParsed('=LAMBDA(a,b,1)', {
|
|
941
|
+
type: 'LambdaExpression',
|
|
942
|
+
body: { type: 'Literal', value: 1, raw: '1' },
|
|
943
|
+
params: [
|
|
944
|
+
{ type: 'Identifier', name: 'a' },
|
|
945
|
+
{ type: 'Identifier', name: 'b' }
|
|
946
|
+
]
|
|
947
|
+
});
|
|
948
|
+
t.isParsed('=LAMBDA(a,b,1)', {
|
|
949
|
+
type: 'LambdaExpression',
|
|
950
|
+
body: { type: 'Literal', value: 1, raw: '1' },
|
|
951
|
+
params: [
|
|
952
|
+
{ type: 'Identifier', name: 'a' },
|
|
953
|
+
{ type: 'Identifier', name: 'b' }
|
|
954
|
+
]
|
|
955
|
+
});
|
|
956
|
+
t.isParsed('=lambda(a,b,a*b)', {
|
|
957
|
+
type: 'LambdaExpression',
|
|
958
|
+
body: {
|
|
959
|
+
type: 'BinaryExpression',
|
|
960
|
+
operator: '*',
|
|
961
|
+
arguments: [
|
|
962
|
+
{ type: 'ReferenceIdentifier', value: 'a', kind: 'name' },
|
|
963
|
+
{ type: 'ReferenceIdentifier', value: 'b', kind: 'name' }
|
|
964
|
+
]
|
|
965
|
+
},
|
|
966
|
+
params: [
|
|
967
|
+
{ type: 'Identifier', name: 'a' },
|
|
968
|
+
{ type: 'Identifier', name: 'b' }
|
|
969
|
+
]
|
|
970
|
+
});
|
|
971
|
+
t.isParsed('=lambda(a,b,a*b)', {
|
|
972
|
+
type: 'LambdaExpression',
|
|
973
|
+
body: {
|
|
974
|
+
type: 'BinaryExpression',
|
|
975
|
+
operator: '*',
|
|
976
|
+
arguments: [
|
|
977
|
+
{ type: 'ReferenceIdentifier', value: 'a', kind: 'name' },
|
|
978
|
+
{ type: 'ReferenceIdentifier', value: 'b', kind: 'name' }
|
|
979
|
+
]
|
|
980
|
+
},
|
|
981
|
+
params: [
|
|
982
|
+
{ type: 'Identifier', name: 'a' },
|
|
983
|
+
{ type: 'Identifier', name: 'b' }
|
|
984
|
+
]
|
|
985
|
+
});
|
|
986
|
+
t.isParsed('=lambda( a , b , a b )', {
|
|
987
|
+
type: 'LambdaExpression',
|
|
988
|
+
body: {
|
|
989
|
+
type: 'BinaryExpression',
|
|
990
|
+
operator: ' ',
|
|
991
|
+
arguments: [
|
|
992
|
+
{ type: 'ReferenceIdentifier', value: 'a', kind: 'name' },
|
|
993
|
+
{ type: 'ReferenceIdentifier', value: 'b', kind: 'name' }
|
|
994
|
+
]
|
|
995
|
+
},
|
|
996
|
+
params: [
|
|
997
|
+
{ type: 'Identifier', name: 'a' },
|
|
998
|
+
{ type: 'Identifier', name: 'b' }
|
|
999
|
+
]
|
|
1000
|
+
});
|
|
1001
|
+
// r and c are forbidden as names, but should work here
|
|
1002
|
+
t.isParsed('=LAMBDA(r,c,r*c)', {
|
|
1003
|
+
type: 'LambdaExpression',
|
|
1004
|
+
body: {
|
|
1005
|
+
type: 'BinaryExpression',
|
|
1006
|
+
operator: '*',
|
|
1007
|
+
arguments: [
|
|
1008
|
+
{ type: 'ReferenceIdentifier', value: 'r', kind: 'name' },
|
|
1009
|
+
{ type: 'ReferenceIdentifier', value: 'c', kind: 'name' }
|
|
1010
|
+
]
|
|
1011
|
+
},
|
|
1012
|
+
params: [
|
|
1013
|
+
{ type: 'Identifier', name: 'r' },
|
|
1014
|
+
{ type: 'Identifier', name: 'c' }
|
|
1015
|
+
]
|
|
1016
|
+
});
|
|
1017
|
+
t.end();
|
|
1018
|
+
});
|
|
1019
|
+
|
|
1020
|
+
test('parser allows calling refs, lambda, let, and call expressions', t => {
|
|
1021
|
+
t.isInvalidExpr('1()');
|
|
1022
|
+
t.isInvalidExpr('"str"()');
|
|
1023
|
+
t.isInvalidExpr('#VALUE!()');
|
|
1024
|
+
t.isInvalidExpr('foo%()');
|
|
1025
|
+
t.isInvalidExpr('foo ()');
|
|
1026
|
+
|
|
1027
|
+
t.isParsed('=lambda()()', {
|
|
1028
|
+
type: 'CallExpression',
|
|
1029
|
+
callee: {
|
|
1030
|
+
type: 'LambdaExpression',
|
|
1031
|
+
params: [],
|
|
1032
|
+
body: null
|
|
1033
|
+
},
|
|
1034
|
+
arguments: []
|
|
1035
|
+
});
|
|
1036
|
+
t.isParsed('=lambda(1)(1)', {
|
|
1037
|
+
type: 'CallExpression',
|
|
1038
|
+
callee: {
|
|
1039
|
+
type: 'LambdaExpression',
|
|
1040
|
+
params: [],
|
|
1041
|
+
body: { type: 'Literal', value: 1, raw: '1' }
|
|
1042
|
+
},
|
|
1043
|
+
arguments: [
|
|
1044
|
+
{ type: 'Literal', value: 1, raw: '1' }
|
|
1045
|
+
]
|
|
1046
|
+
});
|
|
1047
|
+
t.isParsed('=FOO()()', {
|
|
1048
|
+
type: 'CallExpression',
|
|
1049
|
+
callee: {
|
|
1050
|
+
type: 'CallExpression',
|
|
1051
|
+
callee: { type: 'Identifier', name: 'FOO' },
|
|
1052
|
+
arguments: []
|
|
1053
|
+
},
|
|
1054
|
+
arguments: []
|
|
1055
|
+
});
|
|
1056
|
+
t.isParsed('=(A1)()', {
|
|
1057
|
+
type: 'CallExpression',
|
|
1058
|
+
callee: { type: 'ReferenceIdentifier', value: 'A1', kind: 'range' },
|
|
1059
|
+
arguments: []
|
|
1060
|
+
});
|
|
1061
|
+
t.isParsed('=LET(a,1,a)()', {
|
|
1062
|
+
type: 'CallExpression',
|
|
1063
|
+
callee: {
|
|
1064
|
+
type: 'LetExpression',
|
|
1065
|
+
declarations: [
|
|
1066
|
+
{ type: 'LetDeclarator',
|
|
1067
|
+
id: { type: 'Identifier', name: 'a' },
|
|
1068
|
+
init: { type: 'Literal', value: 1, raw: '1' }
|
|
1069
|
+
}
|
|
1070
|
+
],
|
|
1071
|
+
body: { type: 'ReferenceIdentifier', value: 'a', kind: 'name' }
|
|
1072
|
+
},
|
|
1073
|
+
arguments: []
|
|
1074
|
+
});
|
|
1075
|
+
t.isParsed('=#REF!()', {
|
|
1076
|
+
type: 'CallExpression',
|
|
1077
|
+
callee: {
|
|
1078
|
+
type: 'ErrorLiteral',
|
|
1079
|
+
value: '#REF!',
|
|
1080
|
+
raw: '#REF!'
|
|
1081
|
+
},
|
|
1082
|
+
arguments: []
|
|
1083
|
+
});
|
|
1084
|
+
// this is allowed because in Excel: `foo#()` is really `ANCHORARRAY(foo)()`
|
|
1085
|
+
t.isParsed('foo#()', {
|
|
1086
|
+
type: 'CallExpression',
|
|
1087
|
+
callee: {
|
|
1088
|
+
type: 'UnaryExpression', operator: '#', arguments: [
|
|
1089
|
+
{ type: 'ReferenceIdentifier', value: 'foo', kind: 'name' }
|
|
1090
|
+
]
|
|
1091
|
+
},
|
|
1092
|
+
arguments: []
|
|
1093
|
+
});
|
|
1094
|
+
// `@1()` works in Excel because it is really `SINGLE(foo)()`
|
|
1095
|
+
t.end();
|
|
1096
|
+
});
|
|
1097
|
+
|
|
1098
|
+
test('parser supports LET expressions', t => {
|
|
1099
|
+
// Argument is not a name
|
|
1100
|
+
t.isInvalidExpr('LET(,)');
|
|
1101
|
+
t.isInvalidExpr('LET(1,a,1)');
|
|
1102
|
+
// Unexpected end of arguments
|
|
1103
|
+
t.isInvalidExpr('LET()');
|
|
1104
|
+
t.isInvalidExpr('LET(a,b)');
|
|
1105
|
+
t.isInvalidExpr('LET(a,)');
|
|
1106
|
+
// Unexpected argument following calculation
|
|
1107
|
+
t.isInvalidExpr('LET(a,a,1,1)');
|
|
1108
|
+
t.isInvalidExpr('LET(a,a,1,a)');
|
|
1109
|
+
t.isInvalidExpr('LET(a,1,b,1,c,1,a1+b,1)');
|
|
1110
|
+
// Duplicate name: a
|
|
1111
|
+
t.isInvalidExpr('LET(a,1,a,1,1)');
|
|
1112
|
+
t.isInvalidExpr('LET(a,1,A,1,1)');
|
|
1113
|
+
|
|
1114
|
+
t.isParsed('=LET(a,1,)', {
|
|
1115
|
+
type: 'LetExpression',
|
|
1116
|
+
declarations: [
|
|
1117
|
+
{
|
|
1118
|
+
type: 'LetDeclarator',
|
|
1119
|
+
id: { type: 'Identifier', name: 'a' },
|
|
1120
|
+
init: { type: 'Literal', value: 1, raw: '1' }
|
|
1121
|
+
}
|
|
1122
|
+
],
|
|
1123
|
+
body: null
|
|
1124
|
+
});
|
|
1125
|
+
t.isParsed('=LET(a,1,a)', {
|
|
1126
|
+
type: 'LetExpression',
|
|
1127
|
+
declarations: [
|
|
1128
|
+
{
|
|
1129
|
+
type: 'LetDeclarator',
|
|
1130
|
+
id: { type: 'Identifier', name: 'a' },
|
|
1131
|
+
init: { type: 'Literal', value: 1, raw: '1' }
|
|
1132
|
+
}
|
|
1133
|
+
],
|
|
1134
|
+
body: { type: 'ReferenceIdentifier', value: 'a', kind: 'name' }
|
|
1135
|
+
});
|
|
1136
|
+
t.isParsed('=LET(a,1,b,1,c,1,a+b*c)', {
|
|
1137
|
+
type: 'LetExpression',
|
|
1138
|
+
declarations: [
|
|
1139
|
+
{ type: 'LetDeclarator',
|
|
1140
|
+
id: { type: 'Identifier', name: 'a' },
|
|
1141
|
+
init: { type: 'Literal', value: 1, raw: '1' } },
|
|
1142
|
+
{ type: 'LetDeclarator',
|
|
1143
|
+
id: { type: 'Identifier', name: 'b' },
|
|
1144
|
+
init: { type: 'Literal', value: 1, raw: '1' } },
|
|
1145
|
+
{ type: 'LetDeclarator',
|
|
1146
|
+
id: { type: 'Identifier', name: 'c' },
|
|
1147
|
+
init: { type: 'Literal', value: 1, raw: '1' } }
|
|
1148
|
+
],
|
|
1149
|
+
body: {
|
|
1150
|
+
type: 'BinaryExpression', operator: '+', arguments: [
|
|
1151
|
+
{ type: 'ReferenceIdentifier', value: 'a', kind: 'name' },
|
|
1152
|
+
{ type: 'BinaryExpression', operator: '*', arguments: [
|
|
1153
|
+
{ type: 'ReferenceIdentifier', value: 'b', kind: 'name' },
|
|
1154
|
+
{ type: 'ReferenceIdentifier', value: 'c', kind: 'name' }
|
|
1155
|
+
] }
|
|
1156
|
+
]
|
|
1157
|
+
}
|
|
1158
|
+
});
|
|
1159
|
+
// r and c are forbidden as names, but should work here
|
|
1160
|
+
t.isParsed('LET(r,1,c,1,r*c)', {
|
|
1161
|
+
type: 'LetExpression',
|
|
1162
|
+
declarations: [
|
|
1163
|
+
{ type: 'LetDeclarator',
|
|
1164
|
+
id: { type: 'Identifier', name: 'r' },
|
|
1165
|
+
init: { type: 'Literal', value: 1, raw: '1' }
|
|
1166
|
+
},
|
|
1167
|
+
{
|
|
1168
|
+
type: 'LetDeclarator',
|
|
1169
|
+
id: { type: 'Identifier', name: 'c' },
|
|
1170
|
+
init: { type: 'Literal', value: 1, raw: '1' }
|
|
1171
|
+
}
|
|
1172
|
+
],
|
|
1173
|
+
body: {
|
|
1174
|
+
type: 'BinaryExpression',
|
|
1175
|
+
operator: '*',
|
|
1176
|
+
arguments: [
|
|
1177
|
+
{ type: 'ReferenceIdentifier', value: 'r', kind: 'name' },
|
|
1178
|
+
{ type: 'ReferenceIdentifier', value: 'c', kind: 'name' }
|
|
1179
|
+
]
|
|
1180
|
+
}
|
|
1181
|
+
});
|
|
1182
|
+
t.end();
|
|
1183
|
+
});
|