@borgar/fx 4.13.0 → 5.0.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.
Files changed (141) hide show
  1. package/dist/index-BMr6cTgc.d.cts +1444 -0
  2. package/dist/index-BMr6cTgc.d.ts +1444 -0
  3. package/dist/index.cjs +3054 -0
  4. package/dist/index.cjs.map +1 -0
  5. package/dist/index.d.cts +1 -0
  6. package/dist/index.d.ts +1 -0
  7. package/dist/index.js +2984 -0
  8. package/dist/index.js.map +1 -0
  9. package/dist/xlsx/index.cjs +3120 -0
  10. package/dist/xlsx/index.cjs.map +1 -0
  11. package/dist/xlsx/index.d.cts +55 -0
  12. package/dist/xlsx/index.d.ts +55 -0
  13. package/dist/xlsx/index.js +3049 -0
  14. package/dist/xlsx/index.js.map +1 -0
  15. package/docs/API.md +2959 -718
  16. package/docs/AST_format.md +2 -2
  17. package/eslint.config.mjs +40 -0
  18. package/lib/a1.spec.ts +32 -0
  19. package/lib/a1.ts +26 -0
  20. package/lib/addA1RangeBounds.ts +50 -0
  21. package/lib/addTokenMeta.spec.ts +166 -0
  22. package/lib/{addTokenMeta.js → addTokenMeta.ts} +53 -33
  23. package/lib/astTypes.ts +211 -0
  24. package/lib/cloneToken.ts +29 -0
  25. package/lib/{constants.js → constants.ts} +6 -3
  26. package/lib/fixRanges.spec.ts +220 -0
  27. package/lib/fixRanges.ts +260 -0
  28. package/lib/fromCol.spec.ts +15 -0
  29. package/lib/{fromCol.js → fromCol.ts} +1 -1
  30. package/lib/index.spec.ts +119 -0
  31. package/lib/index.ts +76 -0
  32. package/lib/isNodeType.ts +151 -0
  33. package/lib/isType.spec.ts +208 -0
  34. package/lib/{isType.js → isType.ts} +26 -25
  35. package/lib/lexers/{advRangeOp.js → advRangeOp.ts} +1 -1
  36. package/lib/lexers/{canEndRange.js → canEndRange.ts} +2 -2
  37. package/lib/lexers/{lexBoolean.js → lexBoolean.ts} +25 -6
  38. package/lib/lexers/{lexContext.js → lexContext.ts} +14 -6
  39. package/lib/lexers/{lexError.js → lexError.ts} +3 -3
  40. package/lib/lexers/{lexFunction.js → lexFunction.ts} +3 -2
  41. package/lib/lexers/lexNameFuncCntx.ts +112 -0
  42. package/lib/lexers/{lexNamed.js → lexNamed.ts} +4 -4
  43. package/lib/lexers/{lexNewLine.js → lexNewLine.ts} +3 -2
  44. package/lib/lexers/{lexNumber.js → lexNumber.ts} +4 -3
  45. package/lib/lexers/{lexOperator.js → lexOperator.ts} +5 -4
  46. package/lib/lexers/lexRange.ts +15 -0
  47. package/lib/lexers/{lexRangeA1.js → lexRangeA1.ts} +11 -7
  48. package/lib/lexers/{lexRangeR1C1.js → lexRangeR1C1.ts} +10 -6
  49. package/lib/lexers/{lexRangeTrim.js → lexRangeTrim.ts} +3 -2
  50. package/lib/lexers/{lexRefOp.js → lexRefOp.ts} +4 -3
  51. package/lib/lexers/{lexString.js → lexString.ts} +3 -3
  52. package/lib/lexers/{lexStructured.js → lexStructured.ts} +5 -5
  53. package/lib/lexers/{lexWhitespace.js → lexWhitespace.ts} +3 -2
  54. package/lib/lexers/sets.ts +51 -0
  55. package/lib/mergeRefTokens.spec.ts +141 -0
  56. package/lib/{mergeRefTokens.js → mergeRefTokens.ts} +14 -9
  57. package/lib/nodeTypes.ts +54 -0
  58. package/lib/parse.spec.ts +1410 -0
  59. package/lib/{parser.js → parse.ts} +81 -63
  60. package/lib/parseA1Range.spec.ts +233 -0
  61. package/lib/parseA1Range.ts +206 -0
  62. package/lib/parseA1Ref.spec.ts +337 -0
  63. package/lib/parseA1Ref.ts +115 -0
  64. package/lib/parseR1C1Range.ts +191 -0
  65. package/lib/parseR1C1Ref.spec.ts +323 -0
  66. package/lib/parseR1C1Ref.ts +127 -0
  67. package/lib/parseRef.spec.ts +90 -0
  68. package/lib/parseRef.ts +240 -0
  69. package/lib/{parseSRange.js → parseSRange.ts} +15 -10
  70. package/lib/parseStructRef.spec.ts +168 -0
  71. package/lib/parseStructRef.ts +76 -0
  72. package/lib/stringifyA1Range.spec.ts +72 -0
  73. package/lib/stringifyA1Range.ts +72 -0
  74. package/lib/stringifyA1Ref.spec.ts +64 -0
  75. package/lib/stringifyA1Ref.ts +59 -0
  76. package/lib/{stringifyPrefix.js → stringifyPrefix.ts} +17 -2
  77. package/lib/stringifyR1C1Range.spec.ts +92 -0
  78. package/lib/stringifyR1C1Range.ts +73 -0
  79. package/lib/stringifyR1C1Ref.spec.ts +63 -0
  80. package/lib/stringifyR1C1Ref.ts +67 -0
  81. package/lib/stringifyStructRef.spec.ts +124 -0
  82. package/lib/stringifyStructRef.ts +113 -0
  83. package/lib/stringifyTokens.ts +15 -0
  84. package/lib/toCol.spec.ts +11 -0
  85. package/lib/{toCol.js → toCol.ts} +4 -4
  86. package/lib/tokenTypes.ts +76 -0
  87. package/lib/tokenize-srefs.spec.ts +429 -0
  88. package/lib/tokenize.spec.ts +2103 -0
  89. package/lib/tokenize.ts +346 -0
  90. package/lib/translate.spec.ts +35 -0
  91. package/lib/translateToA1.spec.ts +247 -0
  92. package/lib/translateToA1.ts +231 -0
  93. package/lib/translateToR1C1.spec.ts +227 -0
  94. package/lib/translateToR1C1.ts +145 -0
  95. package/lib/types.ts +179 -0
  96. package/lib/xlsx/index.spec.ts +27 -0
  97. package/lib/xlsx/index.ts +32 -0
  98. package/package.json +45 -31
  99. package/tsconfig.json +28 -0
  100. package/typedoc-ignore-links.ts +17 -0
  101. package/typedoc.json +41 -0
  102. package/.eslintrc +0 -22
  103. package/benchmark/benchmark.js +0 -48
  104. package/benchmark/formulas.json +0 -15677
  105. package/dist/fx.d.ts +0 -823
  106. package/dist/fx.js +0 -2
  107. package/dist/package.json +0 -1
  108. package/lib/a1.js +0 -348
  109. package/lib/a1.spec.js +0 -458
  110. package/lib/addTokenMeta.spec.js +0 -153
  111. package/lib/astTypes.js +0 -96
  112. package/lib/extraTypes.js +0 -74
  113. package/lib/fixRanges.js +0 -104
  114. package/lib/fixRanges.spec.js +0 -171
  115. package/lib/fromCol.spec.js +0 -11
  116. package/lib/index.js +0 -134
  117. package/lib/index.spec.js +0 -67
  118. package/lib/isType.spec.js +0 -168
  119. package/lib/lexer-srefs.spec.js +0 -324
  120. package/lib/lexer.js +0 -264
  121. package/lib/lexer.spec.js +0 -1953
  122. package/lib/lexers/lexRange.js +0 -8
  123. package/lib/lexers/sets.js +0 -38
  124. package/lib/mergeRefTokens.spec.js +0 -121
  125. package/lib/package.json +0 -1
  126. package/lib/parseRef.js +0 -157
  127. package/lib/parseRef.spec.js +0 -71
  128. package/lib/parseStructRef.js +0 -48
  129. package/lib/parseStructRef.spec.js +0 -164
  130. package/lib/parser.spec.js +0 -1208
  131. package/lib/rc.js +0 -341
  132. package/lib/rc.spec.js +0 -403
  133. package/lib/stringifyStructRef.js +0 -80
  134. package/lib/stringifyStructRef.spec.js +0 -182
  135. package/lib/toCol.spec.js +0 -11
  136. package/lib/translate-toA1.spec.js +0 -214
  137. package/lib/translate-toRC.spec.js +0 -197
  138. package/lib/translate.js +0 -239
  139. package/lib/translate.spec.js +0 -21
  140. package/rollup.config.mjs +0 -22
  141. package/tsd.json +0 -12
package/lib/lexer.spec.js DELETED
@@ -1,1953 +0,0 @@
1
- import { test, Test } from 'tape';
2
- import {
3
- FX_PREFIX, UNKNOWN,
4
- OPERATOR, BOOLEAN, ERROR, NUMBER, FUNCTION, WHITESPACE, STRING,
5
- REF_RANGE, REF_BEAM, REF_NAMED, REF_TERNARY, CONTEXT, CONTEXT_QUOTE, NEWLINE
6
- } from './constants.js';
7
- import { tokenize } from './lexer.js';
8
-
9
- Test.prototype.isTokens = function isTokens (expr, result, opts) {
10
- this.deepEqual(tokenize(expr, { negativeNumbers: false, ...opts }), result, expr);
11
- };
12
- Test.prototype.isTokensNeg = function isTokensNeg (expr, result, opts) {
13
- this.deepEqual(tokenize(expr, { ...opts, negativeNumbers: true }), result, expr);
14
- };
15
-
16
- test('tokenize operators', t => {
17
- t.isTokens('=1>1', [
18
- { type: FX_PREFIX, value: '=' },
19
- { type: NUMBER, value: '1' },
20
- { type: OPERATOR, value: '>' },
21
- { type: NUMBER, value: '1' }
22
- ]);
23
- t.isTokens('=1>=1', [
24
- { type: FX_PREFIX, value: '=' },
25
- { type: NUMBER, value: '1' },
26
- { type: OPERATOR, value: '>=' },
27
- { type: NUMBER, value: '1' }
28
- ]);
29
- t.isTokens('=1=1', [
30
- { type: FX_PREFIX, value: '=' },
31
- { type: NUMBER, value: '1' },
32
- { type: OPERATOR, value: '=' },
33
- { type: NUMBER, value: '1' }
34
- ]);
35
- t.isTokens('=1<>1', [
36
- { type: FX_PREFIX, value: '=' },
37
- { type: NUMBER, value: '1' },
38
- { type: OPERATOR, value: '<>' },
39
- { type: NUMBER, value: '1' }
40
- ]);
41
- t.isTokens('=1<=1', [
42
- { type: FX_PREFIX, value: '=' },
43
- { type: NUMBER, value: '1' },
44
- { type: OPERATOR, value: '<=' },
45
- { type: NUMBER, value: '1' }
46
- ]);
47
- t.isTokens('=1<1', [
48
- { type: FX_PREFIX, value: '=' },
49
- { type: NUMBER, value: '1' },
50
- { type: OPERATOR, value: '<' },
51
- { type: NUMBER, value: '1' }
52
- ]);
53
- t.isTokens('=1+1', [
54
- { type: FX_PREFIX, value: '=' },
55
- { type: NUMBER, value: '1' },
56
- { type: OPERATOR, value: '+' },
57
- { type: NUMBER, value: '1' }
58
- ]);
59
- t.isTokens('=1-1', [
60
- { type: FX_PREFIX, value: '=' },
61
- { type: NUMBER, value: '1' },
62
- { type: OPERATOR, value: '-' },
63
- { type: NUMBER, value: '1' }
64
- ]);
65
- t.isTokens('=1*1', [
66
- { type: FX_PREFIX, value: '=' },
67
- { type: NUMBER, value: '1' },
68
- { type: OPERATOR, value: '*' },
69
- { type: NUMBER, value: '1' }
70
- ]);
71
- t.isTokens('=1/1', [
72
- { type: FX_PREFIX, value: '=' },
73
- { type: NUMBER, value: '1' },
74
- { type: OPERATOR, value: '/' },
75
- { type: NUMBER, value: '1' }
76
- ]);
77
- t.isTokens('=1^1', [
78
- { type: FX_PREFIX, value: '=' },
79
- { type: NUMBER, value: '1' },
80
- { type: OPERATOR, value: '^' },
81
- { type: NUMBER, value: '1' }
82
- ]);
83
- t.isTokens('=1&1', [
84
- { type: FX_PREFIX, value: '=' },
85
- { type: NUMBER, value: '1' },
86
- { type: OPERATOR, value: '&' },
87
- { type: NUMBER, value: '1' }
88
- ]);
89
- t.isTokens('="A"="B"', [
90
- { type: FX_PREFIX, value: '=' },
91
- { type: STRING, value: '"A"' },
92
- { type: OPERATOR, value: '=' },
93
- { type: STRING, value: '"B"' }
94
- ]);
95
- t.isTokens('=A1:INDIRECT("B2",TRUE)', [
96
- { type: FX_PREFIX, value: '=' },
97
- { type: REF_RANGE, value: 'A1' },
98
- { type: OPERATOR, value: ':' },
99
- { type: FUNCTION, value: 'INDIRECT' },
100
- { type: OPERATOR, value: '(' },
101
- { type: STRING, value: '"B2"' },
102
- { type: OPERATOR, value: ',' },
103
- { type: BOOLEAN, value: 'TRUE' },
104
- { type: OPERATOR, value: ')' }
105
- ]);
106
- t.isTokens('=123%', [
107
- { type: FX_PREFIX, value: '=' },
108
- { type: NUMBER, value: '123' },
109
- { type: OPERATOR, value: '%' }
110
- ]);
111
- t.isTokens('=Sheet1!A1', [
112
- { type: FX_PREFIX, value: '=' },
113
- { type: CONTEXT, value: 'Sheet1' },
114
- { type: OPERATOR, value: '!' },
115
- { type: REF_RANGE, value: 'A1' }
116
- ], { mergeRefs: false });
117
- t.isTokens('=Sheet1!A1', [
118
- { type: FX_PREFIX, value: '=' },
119
- { type: REF_RANGE, value: 'Sheet1!A1' }
120
- ]);
121
- t.isTokens('=(A1:C1,A2:C2)', [
122
- { type: FX_PREFIX, value: '=' },
123
- { type: OPERATOR, value: '(' },
124
- { type: REF_RANGE, value: 'A1' },
125
- { type: OPERATOR, value: ':' },
126
- { type: REF_RANGE, value: 'C1' },
127
- { type: OPERATOR, value: ',' },
128
- { type: REF_RANGE, value: 'A2' },
129
- { type: OPERATOR, value: ':' },
130
- { type: REF_RANGE, value: 'C2' },
131
- { type: OPERATOR, value: ')' }
132
- ], { mergeRefs: false });
133
- t.isTokens('=(A1:C1,A2:C2)', [
134
- { type: FX_PREFIX, value: '=' },
135
- { type: OPERATOR, value: '(' },
136
- { type: REF_RANGE, value: 'A1:C1' },
137
- { type: OPERATOR, value: ',' },
138
- { type: REF_RANGE, value: 'A2:C2' },
139
- { type: OPERATOR, value: ')' }
140
- ]);
141
- t.isTokens('=(A1:C1 A2:C2)', [
142
- { type: FX_PREFIX, value: '=' },
143
- { type: OPERATOR, value: '(' },
144
- { type: REF_RANGE, value: 'A1:C1' },
145
- { type: WHITESPACE, value: ' ' }, // INTERSECT
146
- { type: REF_RANGE, value: 'A2:C2' },
147
- { type: OPERATOR, value: ')' }
148
- ]);
149
- t.isTokens('=(A1:C1 A2:C2)', [
150
- { type: FX_PREFIX, value: '=' },
151
- { type: OPERATOR, value: '(' },
152
- { type: REF_RANGE, value: 'A1:C1' },
153
- { type: WHITESPACE, value: ' ' }, // INTERSECT
154
- { type: REF_RANGE, value: 'A2:C2' },
155
- { type: OPERATOR, value: ')' }
156
- ]);
157
- t.isTokens('={1,2,3}', [
158
- { type: FX_PREFIX, value: '=' },
159
- { type: OPERATOR, value: '{' },
160
- { type: NUMBER, value: '1' },
161
- { type: OPERATOR, value: ',' },
162
- { type: NUMBER, value: '2' },
163
- { type: OPERATOR, value: ',' },
164
- { type: NUMBER, value: '3' },
165
- { type: OPERATOR, value: '}' }
166
- ]);
167
- t.isTokens('={1;2;3}', [
168
- { type: FX_PREFIX, value: '=' },
169
- { type: OPERATOR, value: '{' },
170
- { type: NUMBER, value: '1' },
171
- { type: OPERATOR, value: ';' },
172
- { type: NUMBER, value: '2' },
173
- { type: OPERATOR, value: ';' },
174
- { type: NUMBER, value: '3' },
175
- { type: OPERATOR, value: '}' }
176
- ]);
177
- t.isTokens('={1,2;3}', [
178
- { type: FX_PREFIX, value: '=' },
179
- { type: OPERATOR, value: '{' },
180
- { type: NUMBER, value: '1' },
181
- { type: OPERATOR, value: ',' },
182
- { type: NUMBER, value: '2' },
183
- { type: OPERATOR, value: ';' },
184
- { type: NUMBER, value: '3' },
185
- { type: OPERATOR, value: '}' }
186
- ]);
187
- t.isTokens('={"A",33;TRUE,123}', [
188
- { type: FX_PREFIX, value: '=' },
189
- { type: OPERATOR, value: '{' },
190
- { type: STRING, value: '"A"' },
191
- { type: OPERATOR, value: ',' },
192
- { type: NUMBER, value: '33' },
193
- { type: OPERATOR, value: ';' },
194
- { type: BOOLEAN, value: 'TRUE' },
195
- { type: OPERATOR, value: ',' },
196
- { type: NUMBER, value: '123' },
197
- { type: OPERATOR, value: '}' }
198
- ]);
199
- t.isTokens('={A1:B2}', [
200
- { type: FX_PREFIX, value: '=' },
201
- { type: OPERATOR, value: '{' },
202
- { type: REF_RANGE, value: 'A1:B2' },
203
- { type: OPERATOR, value: '}' }
204
- ]);
205
- t.isTokens('={A1:B2,C3:D4}', [
206
- { type: FX_PREFIX, value: '=' },
207
- { type: OPERATOR, value: '{' },
208
- { type: REF_RANGE, value: 'A1:B2' },
209
- { type: OPERATOR, value: ',' },
210
- { type: REF_RANGE, value: 'C3:D4' },
211
- { type: OPERATOR, value: '}' }
212
- ]);
213
- t.end();
214
- });
215
-
216
- test('tokenize functions', t => {
217
- t.isTokens('=TODAY()', [
218
- { type: FX_PREFIX, value: '=' },
219
- { type: FUNCTION, value: 'TODAY' },
220
- { type: OPERATOR, value: '(' },
221
- { type: OPERATOR, value: ')' }
222
- ]);
223
- t.isTokens('=ToDaY()', [
224
- { type: FX_PREFIX, value: '=' },
225
- { type: FUNCTION, value: 'ToDaY' },
226
- { type: OPERATOR, value: '(' },
227
- { type: OPERATOR, value: ')' }
228
- ]);
229
- t.isTokens('=SUM(1)', [
230
- { type: FX_PREFIX, value: '=' },
231
- { type: FUNCTION, value: 'SUM' },
232
- { type: OPERATOR, value: '(' },
233
- { type: NUMBER, value: '1' },
234
- { type: OPERATOR, value: ')' }
235
- ]);
236
- t.isTokens('=N()', [
237
- { type: FX_PREFIX, value: '=' },
238
- { type: FUNCTION, value: 'N' },
239
- { type: OPERATOR, value: '(' },
240
- { type: OPERATOR, value: ')' }
241
- ]);
242
- t.isTokens('=TRUE()', [
243
- { type: FX_PREFIX, value: '=' },
244
- { type: FUNCTION, value: 'TRUE' },
245
- { type: OPERATOR, value: '(' },
246
- { type: OPERATOR, value: ')' }
247
- ]);
248
- t.isTokens('=FALSE()', [
249
- { type: FX_PREFIX, value: '=' },
250
- { type: FUNCTION, value: 'FALSE' },
251
- { type: OPERATOR, value: '(' },
252
- { type: OPERATOR, value: ')' }
253
- ]);
254
- t.isTokens('=@SUM(1)', [
255
- { type: FX_PREFIX, value: '=' },
256
- { type: OPERATOR, value: '@' },
257
- { type: FUNCTION, value: 'SUM' },
258
- { type: OPERATOR, value: '(' },
259
- { type: NUMBER, value: '1' },
260
- { type: OPERATOR, value: ')' }
261
- ]);
262
- t.isTokens('=SUM(1, 2)', [
263
- { type: FX_PREFIX, value: '=' },
264
- { type: FUNCTION, value: 'SUM' },
265
- { type: OPERATOR, value: '(' },
266
- { type: NUMBER, value: '1' },
267
- { type: OPERATOR, value: ',' },
268
- { type: WHITESPACE, value: ' ' },
269
- { type: NUMBER, value: '2' },
270
- { type: OPERATOR, value: ')' }
271
- ]);
272
- t.isTokens('=SUM(1, SUM(2, 3))', [
273
- { type: FX_PREFIX, value: '=' },
274
- { type: FUNCTION, value: 'SUM' },
275
- { type: OPERATOR, value: '(' },
276
- { type: NUMBER, value: '1' },
277
- { type: OPERATOR, value: ',' },
278
- { type: WHITESPACE, value: ' ' },
279
- { type: FUNCTION, value: 'SUM' },
280
- { type: OPERATOR, value: '(' },
281
- { type: NUMBER, value: '2' },
282
- { type: OPERATOR, value: ',' },
283
- { type: WHITESPACE, value: ' ' },
284
- { type: NUMBER, value: '3' },
285
- { type: OPERATOR, value: ')' },
286
- { type: OPERATOR, value: ')' }
287
- ]);
288
- t.isTokens('=INDIRECT("A1",TRUE)', [
289
- { type: FX_PREFIX, value: '=' },
290
- { type: FUNCTION, value: 'INDIRECT' },
291
- { type: OPERATOR, value: '(' },
292
- { type: STRING, value: '"A1"' },
293
- { type: OPERATOR, value: ',' },
294
- { type: BOOLEAN, value: 'TRUE' },
295
- { type: OPERATOR, value: ')' }
296
- ]);
297
- t.isTokens('=BINOM.DIST.REF_RANGE(1)', [
298
- { type: FX_PREFIX, value: '=' },
299
- { type: FUNCTION, value: 'BINOM.DIST.REF_RANGE' },
300
- { type: OPERATOR, value: '(' },
301
- { type: NUMBER, value: '1' },
302
- { type: OPERATOR, value: ')' }
303
- ]);
304
- t.isTokens('=OCT2BIN(1)', [
305
- { type: FX_PREFIX, value: '=' },
306
- { type: FUNCTION, value: 'OCT2BIN' },
307
- { type: OPERATOR, value: '(' },
308
- { type: NUMBER, value: '1' },
309
- { type: OPERATOR, value: ')' }
310
- ]);
311
- t.isTokens('=TEST_FUNC(1)', [
312
- { type: FX_PREFIX, value: '=' },
313
- { type: FUNCTION, value: 'TEST_FUNC' },
314
- { type: OPERATOR, value: '(' },
315
- { type: NUMBER, value: '1' },
316
- { type: OPERATOR, value: ')' }
317
- ]);
318
- t.isTokens('=_xlfn.FOO(1)', [
319
- { type: FX_PREFIX, value: '=' },
320
- { type: FUNCTION, value: '_xlfn.FOO' },
321
- { type: OPERATOR, value: '(' },
322
- { type: NUMBER, value: '1' },
323
- { type: OPERATOR, value: ')' }
324
- ]);
325
- t.isTokens('=_FOO(1)', [
326
- { type: FX_PREFIX, value: '=' },
327
- { type: FUNCTION, value: '_FOO' },
328
- { type: OPERATOR, value: '(' },
329
- { type: NUMBER, value: '1' },
330
- { type: OPERATOR, value: ')' }
331
- ]);
332
- t.isTokens('=\\FOO(1)', [
333
- { type: FX_PREFIX, value: '=' },
334
- { type: REF_NAMED, value: '\\FOO' },
335
- { type: OPERATOR, value: '(' },
336
- { type: NUMBER, value: '1' },
337
- { type: OPERATOR, value: ')' }
338
- ]);
339
- t.isTokens('=9FOO(1)', [
340
- { type: FX_PREFIX, value: '=' },
341
- { type: NUMBER, value: '9' },
342
- { type: FUNCTION, value: 'FOO' },
343
- { type: OPERATOR, value: '(' },
344
- { type: NUMBER, value: '1' },
345
- { type: OPERATOR, value: ')' }
346
- ]);
347
- t.end();
348
- });
349
-
350
- test('tokenize numbers', t => {
351
- t.isTokens('=0', [
352
- { type: FX_PREFIX, value: '=' },
353
- { type: NUMBER, value: '0' }
354
- ]);
355
- t.isTokens('=+0', [
356
- { type: FX_PREFIX, value: '=' },
357
- { type: OPERATOR, value: '+' },
358
- { type: NUMBER, value: '0' }
359
- ]);
360
- t.isTokens('=+1', [
361
- { type: FX_PREFIX, value: '=' },
362
- { type: OPERATOR, value: '+' },
363
- { type: NUMBER, value: '1' }
364
- ]);
365
- t.isTokens('=-0', [
366
- { type: FX_PREFIX, value: '=' },
367
- { type: OPERATOR, value: '-' },
368
- { type: NUMBER, value: '0' }
369
- ]);
370
- t.isTokens('=1123', [
371
- { type: FX_PREFIX, value: '=' },
372
- { type: NUMBER, value: '1123' }
373
- ]);
374
- t.isTokens('=-1123', [
375
- { type: FX_PREFIX, value: '=' },
376
- { type: OPERATOR, value: '-' },
377
- { type: NUMBER, value: '1123' }
378
- ]);
379
- t.isTokens('=1.5', [
380
- { type: FX_PREFIX, value: '=' },
381
- { type: NUMBER, value: '1.5' }
382
- ]);
383
- t.isTokens('=-1.5', [
384
- { type: FX_PREFIX, value: '=' },
385
- { type: OPERATOR, value: '-' },
386
- { type: NUMBER, value: '1.5' }
387
- ]);
388
- t.isTokens('=1234.5678', [
389
- { type: FX_PREFIX, value: '=' },
390
- { type: NUMBER, value: '1234.5678' }
391
- ]);
392
- t.isTokens('=-1234.5678', [
393
- { type: FX_PREFIX, value: '=' },
394
- { type: OPERATOR, value: '-' },
395
- { type: NUMBER, value: '1234.5678' }
396
- ]);
397
- t.isTokens('=1E-1', [
398
- { type: FX_PREFIX, value: '=' },
399
- { type: NUMBER, value: '1E-1' }
400
- ]);
401
- t.isTokens('=1.5E-10', [
402
- { type: FX_PREFIX, value: '=' },
403
- { type: NUMBER, value: '1.5E-10' }
404
- ]);
405
- t.isTokens('=1.55E+100', [
406
- { type: FX_PREFIX, value: '=' },
407
- { type: NUMBER, value: '1.55E+100' }
408
- ]);
409
- t.isTokens('=1.55e+100', [
410
- { type: FX_PREFIX, value: '=' },
411
- { type: NUMBER, value: '1.55e+100' }
412
- ]);
413
- t.end();
414
- });
415
-
416
- test('tokenize negative numbers', t => {
417
- t.isTokensNeg('=-0', [
418
- { type: FX_PREFIX, value: '=' },
419
- { type: NUMBER, value: '-0' }
420
- ]);
421
- t.isTokensNeg('=-1123', [
422
- { type: FX_PREFIX, value: '=' },
423
- { type: NUMBER, value: '-1123' }
424
- ]);
425
- t.isTokensNeg('=-1.5', [
426
- { type: FX_PREFIX, value: '=' },
427
- { type: NUMBER, value: '-1.5' }
428
- ]);
429
- t.isTokensNeg('=-1234.5678', [
430
- { type: FX_PREFIX, value: '=' },
431
- { type: NUMBER, value: '-1234.5678' }
432
- ]);
433
- t.isTokensNeg('=1E-1', [
434
- { type: FX_PREFIX, value: '=' },
435
- { type: NUMBER, value: '1E-1' }
436
- ]);
437
- t.isTokensNeg('=-1E-1', [
438
- { type: FX_PREFIX, value: '=' },
439
- { type: NUMBER, value: '-1E-1' }
440
- ]);
441
- t.isTokensNeg('=1.5E-10', [
442
- { type: FX_PREFIX, value: '=' },
443
- { type: NUMBER, value: '1.5E-10' }
444
- ]);
445
- t.isTokensNeg('=-1.5E-10', [
446
- { type: FX_PREFIX, value: '=' },
447
- { type: NUMBER, value: '-1.5E-10' }
448
- ]);
449
- t.isTokensNeg('-1', [
450
- { type: NUMBER, value: '-1' }
451
- ]);
452
-
453
- //
454
- t.isTokensNeg('=1-1', [
455
- { type: FX_PREFIX, value: '=' },
456
- { type: NUMBER, value: '1' },
457
- { type: OPERATOR, value: '-' },
458
- { type: NUMBER, value: '1' }
459
- ]);
460
- t.isTokensNeg('1--1', [
461
- { type: NUMBER, value: '1' },
462
- { type: OPERATOR, value: '-' },
463
- { type: NUMBER, value: '-1' }
464
- ]);
465
- t.isTokensNeg('1 - -1', [
466
- { type: NUMBER, value: '1' },
467
- { type: WHITESPACE, value: ' ' },
468
- { type: OPERATOR, value: '-' },
469
- { type: WHITESPACE, value: ' ' },
470
- { type: NUMBER, value: '-1' }
471
- ]);
472
- t.isTokensNeg('1 - - 1', [
473
- { type: NUMBER, value: '1' },
474
- { type: WHITESPACE, value: ' ' },
475
- { type: OPERATOR, value: '-' },
476
- { type: WHITESPACE, value: ' ' },
477
- { type: OPERATOR, value: '-' },
478
- { type: WHITESPACE, value: ' ' },
479
- { type: NUMBER, value: '1' }
480
- ]);
481
- t.isTokensNeg('1 \n - \n -1', [
482
- { type: NUMBER, value: '1' },
483
- { type: WHITESPACE, value: ' ' },
484
- { type: NEWLINE, value: '\n' },
485
- { type: WHITESPACE, value: ' ' },
486
- { type: OPERATOR, value: '-' },
487
- { type: WHITESPACE, value: ' ' },
488
- { type: NEWLINE, value: '\n' },
489
- { type: WHITESPACE, value: ' ' },
490
- { type: NUMBER, value: '-1' }
491
- ]);
492
- t.isTokensNeg('-(-1)', [
493
- { type: OPERATOR, value: '-' },
494
- { type: OPERATOR, value: '(' },
495
- { type: NUMBER, value: '-1' },
496
- { type: OPERATOR, value: ')' }
497
- ]);
498
- t.isTokensNeg('-( -1 )', [
499
- { type: OPERATOR, value: '-' },
500
- { type: OPERATOR, value: '(' },
501
- { type: WHITESPACE, value: ' ' },
502
- { type: NUMBER, value: '-1' },
503
- { type: WHITESPACE, value: ' ' },
504
- { type: OPERATOR, value: ')' }
505
- ]);
506
-
507
- t.isTokensNeg('=true-1', [
508
- { type: FX_PREFIX, value: '=' },
509
- { type: BOOLEAN, value: 'true' },
510
- { type: OPERATOR, value: '-' },
511
- { type: NUMBER, value: '1' }
512
- ]);
513
- t.isTokensNeg('=true -1', [
514
- { type: FX_PREFIX, value: '=' },
515
- { type: BOOLEAN, value: 'true' },
516
- { type: WHITESPACE, value: ' ' },
517
- { type: OPERATOR, value: '-' },
518
- { type: NUMBER, value: '1' }
519
- ]);
520
- t.isTokensNeg('=true - 1', [
521
- { type: FX_PREFIX, value: '=' },
522
- { type: BOOLEAN, value: 'true' },
523
- { type: WHITESPACE, value: ' ' },
524
- { type: OPERATOR, value: '-' },
525
- { type: WHITESPACE, value: ' ' },
526
- { type: NUMBER, value: '1' }
527
- ]);
528
- t.isTokensNeg('=#VALUE!-1', [
529
- { type: FX_PREFIX, value: '=' },
530
- { type: ERROR, value: '#VALUE!' },
531
- { type: OPERATOR, value: '-' },
532
- { type: NUMBER, value: '1' }
533
- ]);
534
- t.isTokensNeg('=#VALUE! -1', [
535
- { type: FX_PREFIX, value: '=' },
536
- { type: ERROR, value: '#VALUE!' },
537
- { type: WHITESPACE, value: ' ' },
538
- { type: OPERATOR, value: '-' },
539
- { type: NUMBER, value: '1' }
540
- ]);
541
- t.isTokensNeg('=SUM(-1) -1', [
542
- { type: FX_PREFIX, value: '=' },
543
- { type: FUNCTION, value: 'SUM' },
544
- { type: OPERATOR, value: '(' },
545
- { type: NUMBER, value: '-1' },
546
- { type: OPERATOR, value: ')' },
547
- { type: WHITESPACE, value: ' ' },
548
- { type: OPERATOR, value: '-' },
549
- { type: NUMBER, value: '1' }
550
- ]);
551
- t.isTokensNeg('=SUM( -1)-1', [
552
- { type: FX_PREFIX, value: '=' },
553
- { type: FUNCTION, value: 'SUM' },
554
- { type: OPERATOR, value: '(' },
555
- { type: WHITESPACE, value: ' ' },
556
- { type: NUMBER, value: '-1' },
557
- { type: OPERATOR, value: ')' },
558
- { type: OPERATOR, value: '-' },
559
- { type: NUMBER, value: '1' }
560
- ]);
561
- t.isTokensNeg('=A1-1', [
562
- { type: FX_PREFIX, value: '=' },
563
- { type: REF_RANGE, value: 'A1' },
564
- { type: OPERATOR, value: '-' },
565
- { type: NUMBER, value: '1' }
566
- ]);
567
- t.isTokensNeg('=A1 -1', [
568
- { type: FX_PREFIX, value: '=' },
569
- { type: REF_RANGE, value: 'A1' },
570
- { type: WHITESPACE, value: ' ' },
571
- { type: OPERATOR, value: '-' },
572
- { type: NUMBER, value: '1' }
573
- ]);
574
- t.isTokensNeg('=foo-1', [
575
- { type: FX_PREFIX, value: '=' },
576
- { type: REF_NAMED, value: 'foo' },
577
- { type: OPERATOR, value: '-' },
578
- { type: NUMBER, value: '1' }
579
- ]);
580
- t.isTokensNeg('=foo -1', [
581
- { type: FX_PREFIX, value: '=' },
582
- { type: REF_NAMED, value: 'foo' },
583
- { type: WHITESPACE, value: ' ' },
584
- { type: OPERATOR, value: '-' },
585
- { type: NUMBER, value: '1' }
586
- ]);
587
- t.isTokensNeg('="true"-1', [
588
- { type: FX_PREFIX, value: '=' },
589
- { type: STRING, value: '"true"' },
590
- { type: OPERATOR, value: '-' },
591
- { type: NUMBER, value: '1' }
592
- ]);
593
- t.isTokensNeg('="true" -1', [
594
- { type: FX_PREFIX, value: '=' },
595
- { type: STRING, value: '"true"' },
596
- { type: WHITESPACE, value: ' ' },
597
- { type: OPERATOR, value: '-' },
598
- { type: NUMBER, value: '1' }
599
- ]);
600
-
601
- t.isTokensNeg('=SUM(1)-1', [
602
- { type: FX_PREFIX, value: '=' },
603
- { type: FUNCTION, value: 'SUM' },
604
- { type: OPERATOR, value: '(' },
605
- { type: NUMBER, value: '1' },
606
- { type: OPERATOR, value: ')' },
607
- { type: OPERATOR, value: '-' },
608
- { type: NUMBER, value: '1' }
609
- ]);
610
- t.isTokensNeg('={1, 2, 3}-4', [
611
- { type: FX_PREFIX, value: '=' },
612
- { type: OPERATOR, value: '{' },
613
- { type: NUMBER, value: '1' },
614
- { type: OPERATOR, value: ',' },
615
- { type: WHITESPACE, value: ' ' },
616
- { type: NUMBER, value: '2' },
617
- { type: OPERATOR, value: ',' },
618
- { type: WHITESPACE, value: ' ' },
619
- { type: NUMBER, value: '3' },
620
- { type: OPERATOR, value: '}' },
621
- { type: OPERATOR, value: '-' },
622
- { type: NUMBER, value: '4' }
623
- ]);
624
- t.isTokensNeg('=10%-1', [
625
- { type: FX_PREFIX, value: '=' },
626
- { type: NUMBER, value: '10' },
627
- { type: OPERATOR, value: '%' },
628
- { type: OPERATOR, value: '-' },
629
- { type: NUMBER, value: '1' }
630
- ]);
631
- t.isTokensNeg('=A1#-1', [
632
- { type: FX_PREFIX, value: '=' },
633
- { type: REF_RANGE, value: 'A1' },
634
- { type: OPERATOR, value: '#' },
635
- { type: OPERATOR, value: '-' },
636
- { type: NUMBER, value: '1' }
637
- ]);
638
- t.end();
639
- });
640
-
641
- test('tokenize simple equations', t => {
642
- t.isTokens('=1 + 2', [
643
- { type: FX_PREFIX, value: '=' },
644
- { type: NUMBER, value: '1' },
645
- { type: WHITESPACE, value: ' ' },
646
- { type: OPERATOR, value: '+' },
647
- { type: WHITESPACE, value: ' ' },
648
- { type: NUMBER, value: '2' }
649
- ]);
650
- t.isTokens('=1+2', [
651
- { type: FX_PREFIX, value: '=' },
652
- { type: NUMBER, value: '1' },
653
- { type: OPERATOR, value: '+' },
654
- { type: NUMBER, value: '2' }
655
- ]);
656
- t.isTokens('=1.1+2.2', [
657
- { type: FX_PREFIX, value: '=' },
658
- { type: NUMBER, value: '1.1' },
659
- { type: OPERATOR, value: '+' },
660
- { type: NUMBER, value: '2.2' }
661
- ]);
662
- t.isTokens('=(1 + 2) - 3', [
663
- { type: FX_PREFIX, value: '=' },
664
- { type: OPERATOR, value: '(' },
665
- { type: NUMBER, value: '1' },
666
- { type: WHITESPACE, value: ' ' },
667
- { type: OPERATOR, value: '+' },
668
- { type: WHITESPACE, value: ' ' },
669
- { type: NUMBER, value: '2' },
670
- { type: OPERATOR, value: ')' },
671
- { type: WHITESPACE, value: ' ' },
672
- { type: OPERATOR, value: '-' },
673
- { type: WHITESPACE, value: ' ' },
674
- { type: NUMBER, value: '3' }
675
- ]);
676
- t.isTokens(' = ( 1.1+2 ) - 3 ', [
677
- { type: WHITESPACE, value: ' ' },
678
- { type: OPERATOR, value: '=' }, // FX_PREFIX?
679
- { type: WHITESPACE, value: ' ' },
680
- { type: OPERATOR, value: '(' },
681
- { type: WHITESPACE, value: ' ' },
682
- { type: NUMBER, value: '1.1' },
683
- { type: OPERATOR, value: '+' },
684
- { type: NUMBER, value: '2' },
685
- { type: WHITESPACE, value: ' ' },
686
- { type: OPERATOR, value: ')' },
687
- { type: WHITESPACE, value: ' ' },
688
- { type: OPERATOR, value: '-' },
689
- { type: WHITESPACE, value: ' ' },
690
- { type: NUMBER, value: '3' },
691
- { type: WHITESPACE, value: ' ' }
692
- ]);
693
- t.isTokens('=1+2*3', [
694
- { type: FX_PREFIX, value: '=' },
695
- { type: NUMBER, value: '1' },
696
- { type: OPERATOR, value: '+' },
697
- { type: NUMBER, value: '2' },
698
- { type: OPERATOR, value: '*' },
699
- { type: NUMBER, value: '3' }
700
- ]);
701
- t.isTokens('= 1+2*3', [
702
- { type: FX_PREFIX, value: '=' },
703
- { type: WHITESPACE, value: ' ' },
704
- { type: NUMBER, value: '1' },
705
- { type: OPERATOR, value: '+' },
706
- { type: NUMBER, value: '2' },
707
- { type: OPERATOR, value: '*' },
708
- { type: NUMBER, value: '3' }
709
- ]);
710
- t.isTokens('=1%', [
711
- { type: FX_PREFIX, value: '=' },
712
- { type: NUMBER, value: '1' },
713
- { type: OPERATOR, value: '%' }
714
- ]);
715
- t.isTokens('=-1%', [
716
- { type: FX_PREFIX, value: '=' },
717
- { type: OPERATOR, value: '-' },
718
- { type: NUMBER, value: '1' },
719
- { type: OPERATOR, value: '%' }
720
- ]);
721
- t.isTokens('=-(1 + 2)%', [
722
- { type: FX_PREFIX, value: '=' },
723
- { type: OPERATOR, value: '-' },
724
- { type: OPERATOR, value: '(' },
725
- { type: NUMBER, value: '1' },
726
- { type: WHITESPACE, value: ' ' },
727
- { type: OPERATOR, value: '+' },
728
- { type: WHITESPACE, value: ' ' },
729
- { type: NUMBER, value: '2' },
730
- { type: OPERATOR, value: ')' },
731
- { type: OPERATOR, value: '%' }
732
- ]);
733
- t.end();
734
- });
735
-
736
- test('tokenize R1C1 style references', t => {
737
- // How R1C1 ranges are merged doesn't make a whole lot of sense.
738
- // A "unit" in A1 is (A1 or A:A or 1:1), this can be merged as
739
- // not all of these make sense but are "theoretically possible"
740
- t.isTokens('=R', [
741
- { type: FX_PREFIX, value: '=' },
742
- { type: REF_BEAM, value: 'R' }
743
- ], { r1c1: true });
744
- t.isTokens('=R:R', [
745
- { type: FX_PREFIX, value: '=' },
746
- { type: REF_BEAM, value: 'R:R' }
747
- ], { r1c1: true });
748
-
749
- t.isTokens('=R1', [
750
- { type: FX_PREFIX, value: '=' },
751
- { type: REF_BEAM, value: 'R1' }
752
- ], { r1c1: true });
753
- t.isTokens('=R1:R1', [
754
- { type: FX_PREFIX, value: '=' },
755
- { type: REF_BEAM, value: 'R1:R1' }
756
- ], { r1c1: true });
757
-
758
- t.isTokens('=R[1]', [
759
- { type: FX_PREFIX, value: '=' },
760
- { type: REF_BEAM, value: 'R[1]' }
761
- ], { r1c1: true });
762
- t.isTokens('=R[1]:R[1]', [
763
- { type: FX_PREFIX, value: '=' },
764
- { type: REF_BEAM, value: 'R[1]:R[1]' }
765
- ], { r1c1: true });
766
-
767
- t.isTokens('=R[-1]', [
768
- { type: FX_PREFIX, value: '=' },
769
- { type: REF_BEAM, value: 'R[-1]' }
770
- ], { r1c1: true });
771
- t.isTokens('=R[-1]:R[-1]', [
772
- { type: FX_PREFIX, value: '=' },
773
- { type: REF_BEAM, value: 'R[-1]:R[-1]' }
774
- ], { r1c1: true });
775
-
776
- t.isTokens('=C', [
777
- { type: FX_PREFIX, value: '=' },
778
- { type: REF_BEAM, value: 'C' }
779
- ], { r1c1: true });
780
- t.isTokens('=C:C', [
781
- { type: FX_PREFIX, value: '=' },
782
- { type: REF_BEAM, value: 'C:C' }
783
- ], { r1c1: true });
784
-
785
- t.isTokens('=C1', [
786
- { type: FX_PREFIX, value: '=' },
787
- { type: REF_BEAM, value: 'C1' }
788
- ], { r1c1: true });
789
- t.isTokens('=C1:C1', [
790
- { type: FX_PREFIX, value: '=' },
791
- { type: REF_BEAM, value: 'C1:C1' }
792
- ], { r1c1: true });
793
-
794
- t.isTokens('=C[1]', [
795
- { type: FX_PREFIX, value: '=' },
796
- { type: REF_BEAM, value: 'C[1]' }
797
- ], { r1c1: true });
798
- t.isTokens('=C[1]:C[1]', [
799
- { type: FX_PREFIX, value: '=' },
800
- { type: REF_BEAM, value: 'C[1]:C[1]' }
801
- ], { r1c1: true });
802
-
803
- t.isTokens('=C[-1]', [
804
- { type: FX_PREFIX, value: '=' },
805
- { type: REF_BEAM, value: 'C[-1]' }
806
- ], { r1c1: true });
807
- t.isTokens('=C[-1]:C[-1]', [
808
- { type: FX_PREFIX, value: '=' },
809
- { type: REF_BEAM, value: 'C[-1]:C[-1]' }
810
- ], { r1c1: true });
811
-
812
- t.isTokens('=RC', [
813
- { type: FX_PREFIX, value: '=' },
814
- { type: REF_RANGE, value: 'RC' }
815
- ], { r1c1: true });
816
- t.isTokens('=RC:RC', [
817
- { type: FX_PREFIX, value: '=' },
818
- { type: REF_RANGE, value: 'RC:RC' }
819
- ], { r1c1: true });
820
-
821
- t.isTokens('=R1C1', [
822
- { type: FX_PREFIX, value: '=' },
823
- { type: REF_RANGE, value: 'R1C1' }
824
- ], { r1c1: true });
825
- t.isTokens('=R1C1:R1C1', [
826
- { type: FX_PREFIX, value: '=' },
827
- { type: REF_RANGE, value: 'R1C1:R1C1' }
828
- ], { r1c1: true });
829
-
830
- t.isTokens('=R[2]C', [
831
- { type: FX_PREFIX, value: '=' },
832
- { type: REF_RANGE, value: 'R[2]C' }
833
- ], { r1c1: true });
834
- t.isTokens('=R[2]C:R[2]C', [
835
- { type: FX_PREFIX, value: '=' },
836
- { type: REF_RANGE, value: 'R[2]C:R[2]C' }
837
- ], { r1c1: true });
838
-
839
- t.isTokens('=R[-2]C', [
840
- { type: FX_PREFIX, value: '=' },
841
- { type: REF_RANGE, value: 'R[-2]C' }
842
- ], { r1c1: true });
843
- t.isTokens('=R[-2]C:R[-2]C', [
844
- { type: FX_PREFIX, value: '=' },
845
- { type: REF_RANGE, value: 'R[-2]C:R[-2]C' }
846
- ], { r1c1: true });
847
-
848
- t.isTokens('=RC[3]', [
849
- { type: FX_PREFIX, value: '=' },
850
- { type: REF_RANGE, value: 'RC[3]' }
851
- ], { r1c1: true });
852
- t.isTokens('=RC[3]:RC[3]', [
853
- { type: FX_PREFIX, value: '=' },
854
- { type: REF_RANGE, value: 'RC[3]:RC[3]' }
855
- ], { r1c1: true });
856
-
857
- t.isTokens('=RC[-3]', [
858
- { type: FX_PREFIX, value: '=' },
859
- { type: REF_RANGE, value: 'RC[-3]' }
860
- ], { r1c1: true });
861
- t.isTokens('=RC[-3]:RC[-3]', [
862
- { type: FX_PREFIX, value: '=' },
863
- { type: REF_RANGE, value: 'RC[-3]:RC[-3]' }
864
- ], { r1c1: true });
865
-
866
- t.isTokens('=R[2]C[2]', [
867
- { type: FX_PREFIX, value: '=' },
868
- { type: REF_RANGE, value: 'R[2]C[2]' }
869
- ], { r1c1: true });
870
- t.isTokens('=R[2]C[2]:R[2]C[2]', [
871
- { type: FX_PREFIX, value: '=' },
872
- { type: REF_RANGE, value: 'R[2]C[2]:R[2]C[2]' }
873
- ], { r1c1: true });
874
-
875
- t.isTokens('=R[-2]C[-2]', [
876
- { type: FX_PREFIX, value: '=' },
877
- { type: REF_RANGE, value: 'R[-2]C[-2]' }
878
- ], { r1c1: true });
879
- t.isTokens('=R[-2]C[-2]:R[-1]C[-1]', [
880
- { type: FX_PREFIX, value: '=' },
881
- { type: REF_RANGE, value: 'R[-2]C[-2]:R[-1]C[-1]' }
882
- ], { r1c1: true });
883
-
884
- t.isTokens('=[filename]Sheetname!R[-2]C:R[-1]C', [
885
- { type: FX_PREFIX, value: '=' },
886
- { type: REF_RANGE, value: '[filename]Sheetname!R[-2]C:R[-1]C' }
887
- ], { r1c1: true });
888
-
889
- t.isTokens('=[filename]Sheetname!R[-2]C:R[-1]C', [
890
- { type: FX_PREFIX, value: '=' },
891
- { type: CONTEXT, value: '[filename]Sheetname' },
892
- { type: OPERATOR, value: '!' },
893
- { type: REF_RANGE, value: 'R[-2]C' },
894
- { type: OPERATOR, value: ':' },
895
- { type: REF_RANGE, value: 'R[-1]C' }
896
- ], { mergeRefs: false, r1c1: true });
897
-
898
- t.isTokens('=R[-2]C[-2]:R[-1]C[-1]', [
899
- { type: FX_PREFIX, value: '=' },
900
- { type: REF_RANGE, value: 'R[-2]C[-2]:R[-1]C[-1]' }
901
- ], { r1c1: true });
902
- t.isTokens('=R[-2]:R1', [
903
- { type: FX_PREFIX, value: '=' },
904
- { type: REF_BEAM, value: 'R[-2]:R1' }
905
- ], { r1c1: true });
906
-
907
- // should not be merged
908
- t.isTokens('=R:C', [
909
- { type: FX_PREFIX, value: '=' },
910
- { type: REF_BEAM, value: 'R' },
911
- { type: OPERATOR, value: ':' },
912
- { type: REF_BEAM, value: 'C' }
913
- ], { r1c1: true });
914
- t.isTokens('=C[1]:R[-2]', [
915
- { type: FX_PREFIX, value: '=' },
916
- { type: REF_BEAM, value: 'C[1]' },
917
- { type: OPERATOR, value: ':' },
918
- { type: REF_BEAM, value: 'R[-2]' }
919
- ], { r1c1: true });
920
- t.isTokens('=R1:RC', [
921
- { type: FX_PREFIX, value: '=' },
922
- { type: REF_BEAM, value: 'R1' },
923
- { type: OPERATOR, value: ':' },
924
- { type: REF_RANGE, value: 'RC' }
925
- ], { r1c1: true });
926
- t.isTokens('=RC:C1', [
927
- { type: FX_PREFIX, value: '=' },
928
- { type: REF_RANGE, value: 'RC' },
929
- { type: OPERATOR, value: ':' },
930
- { type: REF_BEAM, value: 'C1' }
931
- ], { r1c1: true });
932
-
933
- t.end();
934
- });
935
-
936
- test('tokenize A1 style references', t => {
937
- t.isTokens('=A1', [
938
- { type: FX_PREFIX, value: '=' },
939
- { type: REF_RANGE, value: 'A1' }
940
- ]);
941
-
942
- t.isTokens('=C1', [
943
- { type: FX_PREFIX, value: '=' },
944
- { type: REF_RANGE, value: 'C1' }
945
- ]);
946
-
947
- t.isTokens('=R1', [
948
- { type: FX_PREFIX, value: '=' },
949
- { type: REF_RANGE, value: 'R1' }
950
- ]);
951
-
952
- t.isTokens('=$A$1', [
953
- { type: FX_PREFIX, value: '=' },
954
- { type: REF_RANGE, value: '$A$1' }
955
- ]);
956
-
957
- t.isTokens('=A$1', [
958
- { type: FX_PREFIX, value: '=' },
959
- { type: REF_RANGE, value: 'A$1' }
960
- ]);
961
-
962
- t.isTokens('=$A1', [
963
- { type: FX_PREFIX, value: '=' },
964
- { type: REF_RANGE, value: '$A1' }
965
- ]);
966
-
967
- t.isTokens('=A10:A20', [
968
- { type: FX_PREFIX, value: '=' },
969
- { type: REF_RANGE, value: 'A10:A20' }
970
- ]);
971
-
972
- t.isTokens('=A10.:A20', [
973
- { type: FX_PREFIX, value: '=' },
974
- { type: REF_RANGE, value: 'A10.:A20' }
975
- ]);
976
-
977
- t.isTokens('=A10:.A20', [
978
- { type: FX_PREFIX, value: '=' },
979
- { type: REF_RANGE, value: 'A10:.A20' }
980
- ]);
981
-
982
- t.isTokens('=A10.:.A20', [
983
- { type: FX_PREFIX, value: '=' },
984
- { type: REF_RANGE, value: 'A10.:.A20' }
985
- ]);
986
-
987
- t.isTokens('=A10:E20', [
988
- { type: FX_PREFIX, value: '=' },
989
- { type: REF_RANGE, value: 'A10:E20' }
990
- ]);
991
-
992
- t.isTokens('=A1:C1', [
993
- { type: FX_PREFIX, value: '=' },
994
- { type: REF_RANGE, value: 'A1:C1' }
995
- ]);
996
-
997
- t.isTokens('=5:5', [
998
- { type: FX_PREFIX, value: '=' },
999
- { type: REF_BEAM, value: '5:5' }
1000
- ]);
1001
-
1002
- t.isTokens('=5.:5', [
1003
- { type: FX_PREFIX, value: '=' },
1004
- { type: REF_BEAM, value: '5.:5' }
1005
- ]);
1006
-
1007
- t.isTokens('=5:.5', [
1008
- { type: FX_PREFIX, value: '=' },
1009
- { type: REF_BEAM, value: '5:.5' }
1010
- ]);
1011
-
1012
- t.isTokens('=5.:.5', [
1013
- { type: FX_PREFIX, value: '=' },
1014
- { type: REF_BEAM, value: '5.:.5' }
1015
- ]);
1016
-
1017
- t.isTokens('=15:15', [
1018
- { type: FX_PREFIX, value: '=' },
1019
- { type: REF_BEAM, value: '15:15' }
1020
- ]);
1021
-
1022
- t.isTokens('=H:H', [
1023
- { type: FX_PREFIX, value: '=' },
1024
- { type: REF_BEAM, value: 'H:H' }
1025
- ]);
1026
-
1027
- t.isTokens('=H.:H', [
1028
- { type: FX_PREFIX, value: '=' },
1029
- { type: REF_BEAM, value: 'H.:H' }
1030
- ]);
1031
-
1032
- t.isTokens('=H:.H', [
1033
- { type: FX_PREFIX, value: '=' },
1034
- { type: REF_BEAM, value: 'H:.H' }
1035
- ]);
1036
-
1037
- t.isTokens('=H.:.H', [
1038
- { type: FX_PREFIX, value: '=' },
1039
- { type: REF_BEAM, value: 'H.:.H' }
1040
- ]);
1041
-
1042
- t.isTokens('=AA:JJ', [
1043
- { type: FX_PREFIX, value: '=' },
1044
- { type: REF_BEAM, value: 'AA:JJ' }
1045
- ]);
1046
-
1047
- t.isTokens('=XFD:XFF', [
1048
- { type: FX_PREFIX, value: '=' },
1049
- { type: REF_NAMED, value: 'XFD' },
1050
- { type: OPERATOR, value: ':' },
1051
- { type: REF_NAMED, value: 'XFF' }
1052
- ]);
1053
-
1054
- t.isTokens('=Sheetname!A1', [
1055
- { type: FX_PREFIX, value: '=' },
1056
- { type: REF_RANGE, value: 'Sheetname!A1' }
1057
- ]);
1058
-
1059
- t.isTokens('=Sheetname!A1', [
1060
- { type: FX_PREFIX, value: '=' },
1061
- { type: CONTEXT, value: 'Sheetname' },
1062
- { type: OPERATOR, value: '!' },
1063
- { type: REF_RANGE, value: 'A1' }
1064
- ], { mergeRefs: false });
1065
-
1066
- t.isTokens('=Sheet1!A1:B2', [
1067
- { type: FX_PREFIX, value: '=' },
1068
- { type: REF_RANGE, value: 'Sheet1!A1:B2' }
1069
- ]);
1070
-
1071
- t.isTokens('=Sheet1!A1:B2', [
1072
- { type: FX_PREFIX, value: '=' },
1073
- { type: CONTEXT, value: 'Sheet1' },
1074
- { type: OPERATOR, value: '!' },
1075
- { type: REF_RANGE, value: 'A1' },
1076
- { type: OPERATOR, value: ':' },
1077
- { type: REF_RANGE, value: 'B2' }
1078
- ], { mergeRefs: false });
1079
-
1080
- t.isTokens("='Sheet name'!A1:B2", [
1081
- { type: FX_PREFIX, value: '=' },
1082
- { type: REF_RANGE, value: "'Sheet name'!A1:B2" }
1083
- ]);
1084
-
1085
- t.isTokens("='Sheet name'!A1:B2", [
1086
- { type: FX_PREFIX, value: '=' },
1087
- { type: CONTEXT_QUOTE, value: "'Sheet name'" },
1088
- { type: OPERATOR, value: '!' },
1089
- { type: REF_RANGE, value: 'A1' },
1090
- { type: OPERATOR, value: ':' },
1091
- { type: REF_RANGE, value: 'B2' }
1092
- ], { mergeRefs: false });
1093
-
1094
- t.isTokens("='Sheets'' name'!A1:B2", [
1095
- { type: FX_PREFIX, value: '=' },
1096
- { type: REF_RANGE, value: "'Sheets'' name'!A1:B2" }
1097
- ]);
1098
-
1099
- t.isTokens("='Sheets'' name'!A1:B2", [
1100
- { type: FX_PREFIX, value: '=' },
1101
- { type: CONTEXT_QUOTE, value: "'Sheets'' name'" },
1102
- { type: OPERATOR, value: '!' },
1103
- { type: REF_RANGE, value: 'A1' },
1104
- { type: OPERATOR, value: ':' },
1105
- { type: REF_RANGE, value: 'B2' }
1106
- ], { mergeRefs: false });
1107
-
1108
- t.isTokens('=[filename]Sheetname!A1', [
1109
- { type: FX_PREFIX, value: '=' },
1110
- { type: REF_RANGE, value: '[filename]Sheetname!A1' }
1111
- ]);
1112
-
1113
- t.isTokens('=[filename]Sheetname!A1', [
1114
- { type: FX_PREFIX, value: '=' },
1115
- { type: CONTEXT, value: '[filename]Sheetname' },
1116
- { type: OPERATOR, value: '!' },
1117
- { type: REF_RANGE, value: 'A1' }
1118
- ], { mergeRefs: false });
1119
-
1120
- t.isTokens("='[filename]Sheets'' name'!A1:B2", [
1121
- { type: FX_PREFIX, value: '=' },
1122
- { type: REF_RANGE, value: "'[filename]Sheets'' name'!A1:B2" }
1123
- ]);
1124
-
1125
- t.isTokens("='[filename]Sheets'' name'!A1:B2", [
1126
- { type: FX_PREFIX, value: '=' },
1127
- { type: CONTEXT_QUOTE, value: "'[filename]Sheets'' name'" },
1128
- { type: OPERATOR, value: '!' },
1129
- { type: REF_RANGE, value: 'A1' },
1130
- { type: OPERATOR, value: ':' },
1131
- { type: REF_RANGE, value: 'B2' }
1132
- ], { mergeRefs: false });
1133
-
1134
- t.isTokens("='Run forest, run!'!A1", [
1135
- { type: FX_PREFIX, value: '=' },
1136
- { type: REF_RANGE, value: '\'Run forest, run!\'!A1' }
1137
- ]);
1138
-
1139
- t.isTokens("='Run forest, run!'!A1", [
1140
- { type: FX_PREFIX, value: '=' },
1141
- { type: CONTEXT_QUOTE, value: "'Run forest, run!'" },
1142
- { type: OPERATOR, value: '!' },
1143
- { type: REF_RANGE, value: 'A1' }
1144
- ], { mergeRefs: false });
1145
-
1146
- t.isTokens("='foo'''!A1", [
1147
- { type: FX_PREFIX, value: '=' },
1148
- { type: REF_RANGE, value: "'foo'''!A1" }
1149
- ]);
1150
-
1151
- t.isTokens("='foo'''!A1", [
1152
- { type: FX_PREFIX, value: '=' },
1153
- { type: CONTEXT_QUOTE, value: "'foo'''" },
1154
- { type: OPERATOR, value: '!' },
1155
- { type: REF_RANGE, value: 'A1' }
1156
- ], { mergeRefs: false });
1157
-
1158
- t.isTokens("='foo'''''!A1", [
1159
- { type: FX_PREFIX, value: '=' },
1160
- { type: REF_RANGE, value: "'foo'''''!A1" }
1161
- ]);
1162
-
1163
- t.isTokens("='foo'''''!A1", [
1164
- { type: FX_PREFIX, value: '=' },
1165
- { type: CONTEXT_QUOTE, value: "'foo'''''" },
1166
- { type: OPERATOR, value: '!' },
1167
- { type: REF_RANGE, value: 'A1' }
1168
- ], { mergeRefs: false });
1169
-
1170
- t.isTokens('=[15]Sheet32!X4', [
1171
- { type: FX_PREFIX, value: '=' },
1172
- { type: REF_RANGE, value: '[15]Sheet32!X4' }
1173
- ]);
1174
-
1175
- // illegal syntax
1176
- t.isTokens('=[15]!named', [
1177
- { type: FX_PREFIX, value: '=' },
1178
- { type: UNKNOWN, value: '[' },
1179
- { type: NUMBER, value: '15' },
1180
- { type: UNKNOWN, value: ']' },
1181
- { type: OPERATOR, value: '!' },
1182
- { type: REF_NAMED, value: 'named' }
1183
- ]);
1184
-
1185
- t.isTokens('=filename!named', [
1186
- { type: FX_PREFIX, value: '=' },
1187
- { type: REF_NAMED, value: 'filename!named' }
1188
- ]);
1189
- t.isTokens('=filename!named', [
1190
- { type: FX_PREFIX, value: '=' },
1191
- { type: CONTEXT, value: 'filename' },
1192
- { type: OPERATOR, value: '!' },
1193
- { type: REF_NAMED, value: 'named' }
1194
- ], { mergeRefs: false });
1195
-
1196
- t.isTokens('=[15]Sheet32!X4', [
1197
- { type: FX_PREFIX, value: '=' },
1198
- { type: CONTEXT, value: '[15]Sheet32' },
1199
- { type: OPERATOR, value: '!' },
1200
- { type: REF_RANGE, value: 'X4' }
1201
- ], { mergeRefs: false });
1202
-
1203
- // largest possible A1 ref (in Excel)
1204
- t.isTokens('=XFD1048576', [
1205
- { type: FX_PREFIX, value: '=' },
1206
- { type: REF_RANGE, value: 'XFD1048576' }
1207
- ]);
1208
- t.isTokens('=XFD1048577', [
1209
- { type: FX_PREFIX, value: '=' },
1210
- { type: REF_NAMED, value: 'XFD1048577' }
1211
- ]);
1212
- t.isTokens('=XFE1048577', [
1213
- { type: FX_PREFIX, value: '=' },
1214
- { type: REF_NAMED, value: 'XFE1048577' }
1215
- ]);
1216
- t.isTokens('=pensioneligibilitypartner1', [
1217
- { type: FX_PREFIX, value: '=' },
1218
- { type: REF_NAMED, value: 'pensioneligibilitypartner1' }
1219
- ]);
1220
-
1221
- //
1222
- t.isTokens("='D:\\Reports\\Sales.xlsx'!namedrange", [
1223
- { type: FX_PREFIX, value: '=' },
1224
- { type: CONTEXT_QUOTE, value: "'D:\\Reports\\Sales.xlsx'" },
1225
- { type: OPERATOR, value: '!' },
1226
- { type: REF_NAMED, value: 'namedrange' }
1227
- ], { mergeRefs: false });
1228
- t.isTokens("='D:\\Reports\\Sales.xlsx'!namedrange", [
1229
- { type: FX_PREFIX, value: '=' },
1230
- { type: REF_NAMED, value: "'D:\\Reports\\Sales.xlsx'!namedrange" }
1231
- ]);
1232
-
1233
- t.isTokens('=Sales.xlsx!namedrange', [
1234
- { type: FX_PREFIX, value: '=' },
1235
- { type: CONTEXT, value: 'Sales.xlsx' },
1236
- { type: OPERATOR, value: '!' },
1237
- { type: REF_NAMED, value: 'namedrange' }
1238
- ], { mergeRefs: false });
1239
- t.isTokens('=Sales.xlsx!namedrange', [
1240
- { type: FX_PREFIX, value: '=' },
1241
- { type: REF_NAMED, value: 'Sales.xlsx!namedrange' }
1242
- ]);
1243
-
1244
- t.isTokens('=Sheet1!A:A', [
1245
- { type: FX_PREFIX, value: '=' },
1246
- { type: REF_BEAM, value: 'Sheet1!A:A' }
1247
- ]);
1248
- t.isTokens('=Sheet1!A:A', [
1249
- { type: FX_PREFIX, value: '=' },
1250
- { type: CONTEXT, value: 'Sheet1' },
1251
- { type: OPERATOR, value: '!' },
1252
- { type: REF_BEAM, value: 'A:A' }
1253
- ], { mergeRefs: false });
1254
-
1255
- t.isTokens('=Sheet1!A:A:B:B', [
1256
- { type: FX_PREFIX, value: '=' },
1257
- { type: REF_BEAM, value: 'Sheet1!A:A' },
1258
- { type: OPERATOR, value: ':' },
1259
- { type: REF_BEAM, value: 'B:B' }
1260
- ]);
1261
- t.isTokens('=Sheet1!A:A:B:B', [
1262
- { type: FX_PREFIX, value: '=' },
1263
- { type: CONTEXT, value: 'Sheet1' },
1264
- { type: OPERATOR, value: '!' },
1265
- { type: REF_BEAM, value: 'A:A' },
1266
- { type: OPERATOR, value: ':' },
1267
- { type: REF_BEAM, value: 'B:B' }
1268
- ], { mergeRefs: false });
1269
-
1270
- t.isTokens('=Sheet1!A.:.A:B.:.B', [
1271
- { type: FX_PREFIX, value: '=' },
1272
- { type: CONTEXT, value: 'Sheet1' },
1273
- { type: OPERATOR, value: '!' },
1274
- { type: REF_BEAM, value: 'A.:.A' },
1275
- { type: OPERATOR, value: ':' },
1276
- { type: REF_BEAM, value: 'B.:.B' }
1277
- ], { mergeRefs: false });
1278
-
1279
- t.isTokens('=Sheet1!#REF!:A1', [
1280
- { type: FX_PREFIX, value: '=' },
1281
- { type: CONTEXT, value: 'Sheet1' },
1282
- { type: OPERATOR, value: '!' },
1283
- { type: ERROR, value: '#REF!' },
1284
- { type: OPERATOR, value: ':' },
1285
- { type: REF_RANGE, value: 'A1' }
1286
- ]);
1287
-
1288
- t.end();
1289
- });
1290
-
1291
- test('tokenize errors', t => {
1292
- t.isTokens('=#NAME?', [
1293
- { type: FX_PREFIX, value: '=' },
1294
- { type: ERROR, value: '#NAME?' }
1295
- ]);
1296
- t.isTokens('=#VALUE!', [
1297
- { type: FX_PREFIX, value: '=' },
1298
- { type: ERROR, value: '#VALUE!' }
1299
- ]);
1300
- t.isTokens('=#REF!', [
1301
- { type: FX_PREFIX, value: '=' },
1302
- { type: ERROR, value: '#REF!' }
1303
- ]);
1304
- t.isTokens('=#DIV/0!', [
1305
- { type: FX_PREFIX, value: '=' },
1306
- { type: ERROR, value: '#DIV/0!' }
1307
- ]);
1308
- t.isTokens('=#NULL!', [
1309
- { type: FX_PREFIX, value: '=' },
1310
- { type: ERROR, value: '#NULL!' }
1311
- ]);
1312
- t.isTokens('=#NUM!', [
1313
- { type: FX_PREFIX, value: '=' },
1314
- { type: ERROR, value: '#NUM!' }
1315
- ]);
1316
- t.isTokens('=#N/A', [
1317
- { type: FX_PREFIX, value: '=' },
1318
- { type: ERROR, value: '#N/A' }
1319
- ]);
1320
- t.isTokens('=#GETTING_DATA', [
1321
- { type: FX_PREFIX, value: '=' },
1322
- { type: ERROR, value: '#GETTING_DATA' }
1323
- ]);
1324
- t.isTokens('=#SPILL!', [
1325
- { type: FX_PREFIX, value: '=' },
1326
- { type: ERROR, value: '#SPILL!' }
1327
- ]);
1328
- t.isTokens('=#UNKNOWN!', [
1329
- { type: FX_PREFIX, value: '=' },
1330
- { type: ERROR, value: '#UNKNOWN!' }
1331
- ]);
1332
- t.isTokens('=#FIELD!', [
1333
- { type: FX_PREFIX, value: '=' },
1334
- { type: ERROR, value: '#FIELD!' }
1335
- ]);
1336
- t.isTokens('=#CALC!', [
1337
- { type: FX_PREFIX, value: '=' },
1338
- { type: ERROR, value: '#CALC!' }
1339
- ]);
1340
- t.isTokens('=#SYNTAX?', [
1341
- { type: FX_PREFIX, value: '=' },
1342
- { type: ERROR, value: '#SYNTAX?' }
1343
- ]);
1344
- t.isTokens('=#ERROR!', [
1345
- { type: FX_PREFIX, value: '=' },
1346
- { type: ERROR, value: '#ERROR!' }
1347
- ]);
1348
- t.isTokens('=#CONNECT!', [
1349
- { type: FX_PREFIX, value: '=' },
1350
- { type: ERROR, value: '#CONNECT!' }
1351
- ]);
1352
- t.isTokens('=#BLOCKED!', [
1353
- { type: FX_PREFIX, value: '=' },
1354
- { type: ERROR, value: '#BLOCKED!' }
1355
- ]);
1356
- t.isTokens('=#EXTERNAL!', [
1357
- { type: FX_PREFIX, value: '=' },
1358
- { type: ERROR, value: '#EXTERNAL!' }
1359
- ]);
1360
-
1361
- // TODO: is this really what should happen?
1362
- t.isTokens('=#NONSENSE!', [
1363
- { type: FX_PREFIX, value: '=' },
1364
- { type: OPERATOR, value: '#' },
1365
- { type: CONTEXT, value: 'NONSENSE' },
1366
- { type: OPERATOR, value: '!' }
1367
- ]);
1368
-
1369
- t.end();
1370
- });
1371
-
1372
- test('tokenize booleans', t => {
1373
- t.isTokens('=true', [
1374
- { type: FX_PREFIX, value: '=' },
1375
- { type: BOOLEAN, value: 'true' }
1376
- ]);
1377
- t.isTokens('=tRuE', [
1378
- { type: FX_PREFIX, value: '=' },
1379
- { type: BOOLEAN, value: 'tRuE' }
1380
- ]);
1381
- t.isTokens('=TRUE', [
1382
- { type: FX_PREFIX, value: '=' },
1383
- { type: BOOLEAN, value: 'TRUE' }
1384
- ]);
1385
- t.isTokens('=false', [
1386
- { type: FX_PREFIX, value: '=' },
1387
- { type: BOOLEAN, value: 'false' }
1388
- ]);
1389
- t.isTokens('=fAlSe', [
1390
- { type: FX_PREFIX, value: '=' },
1391
- { type: BOOLEAN, value: 'fAlSe' }
1392
- ]);
1393
- t.isTokens('=FALSE', [
1394
- { type: FX_PREFIX, value: '=' },
1395
- { type: BOOLEAN, value: 'FALSE' }
1396
- ]);
1397
- t.end();
1398
- });
1399
-
1400
- test('tokenize strings', t => {
1401
- t.isTokens('=""', [
1402
- { type: FX_PREFIX, value: '=' },
1403
- { type: STRING, value: '""' }
1404
- ]);
1405
- t.isTokens('=""""', [
1406
- { type: FX_PREFIX, value: '=' },
1407
- { type: STRING, value: '""""' }
1408
- ]);
1409
- t.isTokens('="data"', [
1410
- { type: FX_PREFIX, value: '=' },
1411
- { type: STRING, value: '"data"' }
1412
- ]);
1413
- t.isTokens('="data""data"', [
1414
- { type: FX_PREFIX, value: '=' },
1415
- { type: STRING, value: '"data""data"' }
1416
- ]);
1417
- t.isTokens('="data"&"data"', [
1418
- { type: FX_PREFIX, value: '=' },
1419
- { type: STRING, value: '"data"' },
1420
- { type: OPERATOR, value: '&' },
1421
- { type: STRING, value: '"data"' }
1422
- ]);
1423
- t.isTokens('="data"&"data"&"data"', [
1424
- { type: FX_PREFIX, value: '=' },
1425
- { type: STRING, value: '"data"' },
1426
- { type: OPERATOR, value: '&' },
1427
- { type: STRING, value: '"data"' },
1428
- { type: OPERATOR, value: '&' },
1429
- { type: STRING, value: '"data"' }
1430
- ]);
1431
- // we should be able to highlight things that are still being typed
1432
- // so open-ended STRING, PATH_BRACE, and PATH_QUOTE tokens at the
1433
- // end of output are tagged.
1434
- t.isTokens('="incomple', [
1435
- { type: FX_PREFIX, value: '=' },
1436
- { type: STRING, value: '"incomple', unterminated: true }
1437
- ]);
1438
-
1439
- t.isTokens('="', [
1440
- { type: FX_PREFIX, value: '=' },
1441
- { type: STRING, value: '"', unterminated: true }
1442
- ]);
1443
- t.isTokens('=""', [
1444
- { type: FX_PREFIX, value: '=' },
1445
- { type: STRING, value: '""' }
1446
- ]);
1447
- t.isTokens('="""', [
1448
- { type: FX_PREFIX, value: '=' },
1449
- { type: STRING, value: '"""', unterminated: true }
1450
- ]);
1451
- t.isTokens('=""""', [
1452
- { type: FX_PREFIX, value: '=' },
1453
- { type: STRING, value: '""""' }
1454
- ]);
1455
- t.isTokens('="""""', [
1456
- { type: FX_PREFIX, value: '=' },
1457
- { type: STRING, value: '"""""', unterminated: true }
1458
- ]);
1459
- t.isTokens('=""""""', [
1460
- { type: FX_PREFIX, value: '=' },
1461
- { type: STRING, value: '""""""' }
1462
- ]);
1463
- t.isTokens('="aa""ss', [
1464
- { type: FX_PREFIX, value: '=' },
1465
- { type: STRING, value: '"aa""ss', unterminated: true }
1466
- ]);
1467
- t.isTokens('="aa""ss"', [
1468
- { type: FX_PREFIX, value: '=' },
1469
- { type: STRING, value: '"aa""ss"' }
1470
- ]);
1471
- t.isTokens('="aa""', [
1472
- { type: FX_PREFIX, value: '=' },
1473
- { type: STRING, value: '"aa""', unterminated: true }
1474
- ]);
1475
- t.isTokens('="aa"""', [
1476
- { type: FX_PREFIX, value: '=' },
1477
- { type: STRING, value: '"aa"""' }
1478
- ]);
1479
-
1480
- t.end();
1481
- });
1482
-
1483
- test('unknown and unary minus mess with offsets', t => {
1484
- t.isTokens('=-1', [
1485
- { type: FX_PREFIX, value: '=', loc: [ 0, 1 ] },
1486
- { type: OPERATOR, value: '-', loc: [ 1, 2 ] },
1487
- { type: NUMBER, value: '1', loc: [ 2, 3 ] }
1488
- ], { withLocation: true });
1489
- t.isTokens('=-1', [
1490
- { type: FX_PREFIX, value: '=', loc: [ 0, 1 ] },
1491
- { type: NUMBER, value: '-1', loc: [ 1, 3 ] }
1492
- ], { withLocation: true, negativeNumbers: true });
1493
-
1494
- t.isTokens('=$C', [
1495
- { type: FX_PREFIX, value: '=', loc: [ 0, 1 ] },
1496
- { type: UNKNOWN, value: '$C', loc: [ 1, 3 ] }
1497
- ], { withLocation: true });
1498
- t.isTokens('=$C.foo', [
1499
- { type: FX_PREFIX, value: '=', loc: [ 0, 1 ] },
1500
- { type: UNKNOWN, value: '$C.foo', loc: [ 1, 7 ] }
1501
- ], { withLocation: true });
1502
-
1503
- t.end();
1504
- });
1505
-
1506
- test('unknowns, named ranges and functions', t => {
1507
- t.isTokens('=foo', [
1508
- { type: FX_PREFIX, value: '=' },
1509
- { type: REF_NAMED, value: 'foo' }
1510
- ]);
1511
- t.isTokens('=_foo', [
1512
- { type: FX_PREFIX, value: '=' },
1513
- { type: REF_NAMED, value: '_foo' }
1514
- ]);
1515
- t.isTokens('=\\foo', [
1516
- { type: FX_PREFIX, value: '=' },
1517
- { type: REF_NAMED, value: '\\foo' }
1518
- ]);
1519
- t.isTokens('=\\fo', [
1520
- { type: FX_PREFIX, value: '=' },
1521
- { type: REF_NAMED, value: '\\fo' }
1522
- ]);
1523
- t.isTokens('=\\f', [
1524
- { type: FX_PREFIX, value: '=' },
1525
- { type: UNKNOWN, value: '\\f' }
1526
- ]);
1527
- t.isTokens('=\\', [
1528
- { type: FX_PREFIX, value: '=' },
1529
- { type: UNKNOWN, value: '\\' }
1530
- ]);
1531
- t.isTokens('=æði', [
1532
- { type: FX_PREFIX, value: '=' },
1533
- { type: REF_NAMED, value: 'æði' }
1534
- ]);
1535
- t.isTokens('=らーめん', [
1536
- { type: FX_PREFIX, value: '=' },
1537
- { type: REF_NAMED, value: 'らーめん' }
1538
- ]);
1539
- t.isTokens('=@foo', [
1540
- { type: FX_PREFIX, value: '=' },
1541
- { type: OPERATOR, value: '@' },
1542
- { type: REF_NAMED, value: 'foo' }
1543
- ]);
1544
- t.isTokens('=9æði', [
1545
- { type: FX_PREFIX, value: '=' },
1546
- { type: NUMBER, value: '9' },
1547
- { type: REF_NAMED, value: 'æði' }
1548
- ]);
1549
- t.isTokens('=¢mah¢', [
1550
- { type: FX_PREFIX, value: '=' },
1551
- { type: REF_NAMED, value: '¢mah¢' }
1552
- ]);
1553
- t.isTokens('=~mah~', [
1554
- { type: FX_PREFIX, value: '=' },
1555
- { type: UNKNOWN, value: '~mah~' }
1556
- ]);
1557
- t.isTokens('=$foo', [
1558
- { type: FX_PREFIX, value: '=' },
1559
- { type: UNKNOWN, value: '$foo' }
1560
- ]);
1561
- t.isTokens('=$zzzz12', [
1562
- { type: FX_PREFIX, value: '=' },
1563
- { type: UNKNOWN, value: '$zzzz12' }
1564
- ]);
1565
- t.isTokens('=~zzzz12()', [
1566
- { type: FX_PREFIX, value: '=' },
1567
- { type: UNKNOWN, value: '~zzzz12' },
1568
- { type: OPERATOR, value: '(' },
1569
- { type: OPERATOR, value: ')' }
1570
- ]);
1571
- t.isTokens('=zzzz~12()', [
1572
- { type: FX_PREFIX, value: '=' },
1573
- { type: UNKNOWN, value: 'zzzz~' },
1574
- { type: NUMBER, value: '12' },
1575
- { type: OPERATOR, value: '(' },
1576
- { type: OPERATOR, value: ')' }
1577
- ]);
1578
- t.end();
1579
- });
1580
-
1581
- test('tokenize partial ranges', t => {
1582
- const opts = { allowTernary: true };
1583
- t.isTokens('1:D$1', [
1584
- { type: REF_TERNARY, value: '1:D$1' }
1585
- ], opts);
1586
-
1587
- t.isTokens('1:D$1', [
1588
- { type: NUMBER, value: '1' },
1589
- { type: OPERATOR, value: ':' },
1590
- { type: REF_RANGE, value: 'D$1' }
1591
- ]);
1592
-
1593
- t.isTokens('B2:B', [
1594
- { type: REF_TERNARY, value: 'B2:B' }
1595
- ], opts);
1596
- t.isTokens('B2:B', [
1597
- { type: REF_RANGE, value: 'B2' },
1598
- { type: OPERATOR, value: ':' },
1599
- { type: REF_NAMED, value: 'B' }
1600
- ]);
1601
-
1602
- // form 1
1603
- t.isTokens('1:A1', [
1604
- { type: REF_TERNARY, value: '1:A1' }
1605
- ], opts);
1606
- t.isTokens('$1:A1', [
1607
- { type: REF_TERNARY, value: '$1:A1' }
1608
- ], opts);
1609
- t.isTokens('1:$A1', [
1610
- { type: REF_TERNARY, value: '1:$A1' }
1611
- ], opts);
1612
- t.isTokens('1:A$1', [
1613
- { type: REF_TERNARY, value: '1:A$1' }
1614
- ], opts);
1615
- t.isTokens('1:$A$1', [
1616
- { type: REF_TERNARY, value: '1:$A$1' }
1617
- ], opts);
1618
- t.isTokens('$1:A$1', [
1619
- { type: REF_TERNARY, value: '$1:A$1' }
1620
- ], opts);
1621
- t.isTokens('$1:$A1', [
1622
- { type: REF_TERNARY, value: '$1:$A1' }
1623
- ], opts);
1624
- t.isTokens('$1:$A$1', [
1625
- { type: REF_TERNARY, value: '$1:$A$1' }
1626
- ], opts);
1627
-
1628
- // form 2
1629
- t.isTokens('A1:1', [
1630
- { type: REF_TERNARY, value: 'A1:1' }
1631
- ], opts);
1632
- t.isTokens('A1:$1', [
1633
- { type: REF_TERNARY, value: 'A1:$1' }
1634
- ], opts);
1635
- t.isTokens('$A1:1', [
1636
- { type: REF_TERNARY, value: '$A1:1' }
1637
- ], opts);
1638
- t.isTokens('A$1:1', [
1639
- { type: REF_TERNARY, value: 'A$1:1' }
1640
- ], opts);
1641
- t.isTokens('$A$1:1', [
1642
- { type: REF_TERNARY, value: '$A$1:1' }
1643
- ], opts);
1644
- t.isTokens('A$1:$1', [
1645
- { type: REF_TERNARY, value: 'A$1:$1' }
1646
- ], opts);
1647
- t.isTokens('$A1:$1', [
1648
- { type: REF_TERNARY, value: '$A1:$1' }
1649
- ], opts);
1650
- t.isTokens('$A$1:$1', [
1651
- { type: REF_TERNARY, value: '$A$1:$1' }
1652
- ], opts);
1653
-
1654
- // form 3
1655
- t.isTokens('A:A1', [
1656
- { type: REF_TERNARY, value: 'A:A1' }
1657
- ], opts);
1658
- t.isTokens('$A:A1', [
1659
- { type: REF_TERNARY, value: '$A:A1' }
1660
- ], opts);
1661
- t.isTokens('A:$A1', [
1662
- { type: REF_TERNARY, value: 'A:$A1' }
1663
- ], opts);
1664
- t.isTokens('A:A$1', [
1665
- { type: REF_TERNARY, value: 'A:A$1' }
1666
- ], opts);
1667
- t.isTokens('A:$A$1', [
1668
- { type: REF_TERNARY, value: 'A:$A$1' }
1669
- ], opts);
1670
- t.isTokens('$A:A$1', [
1671
- { type: REF_TERNARY, value: '$A:A$1' }
1672
- ], opts);
1673
- t.isTokens('$A:$A1', [
1674
- { type: REF_TERNARY, value: '$A:$A1' }
1675
- ], opts);
1676
- t.isTokens('$A:$A$1', [
1677
- { type: REF_TERNARY, value: '$A:$A$1' }
1678
- ], opts);
1679
-
1680
- // form 4
1681
- t.isTokens('A1:A', [
1682
- { type: REF_TERNARY, value: 'A1:A' }
1683
- ], opts);
1684
- t.isTokens('A1:$A', [
1685
- { type: REF_TERNARY, value: 'A1:$A' }
1686
- ], opts);
1687
- t.isTokens('$A1:A', [
1688
- { type: REF_TERNARY, value: '$A1:A' }
1689
- ], opts);
1690
- t.isTokens('A$1:A', [
1691
- { type: REF_TERNARY, value: 'A$1:A' }
1692
- ], opts);
1693
- t.isTokens('$A$1:A', [
1694
- { type: REF_TERNARY, value: '$A$1:A' }
1695
- ], opts);
1696
- t.isTokens('A$1:$A', [
1697
- { type: REF_TERNARY, value: 'A$1:$A' }
1698
- ], opts);
1699
- t.isTokens('$A1:$A', [
1700
- { type: REF_TERNARY, value: '$A1:$A' }
1701
- ], opts);
1702
- t.isTokens('$A$1:$A', [
1703
- { type: REF_TERNARY, value: '$A$1:$A' }
1704
- ], opts);
1705
-
1706
- t.isTokens('=A10:A+B1:2', [
1707
- { type: FX_PREFIX, value: '=' },
1708
- { type: REF_TERNARY, value: 'A10:A' },
1709
- { type: OPERATOR, value: '+' },
1710
- { type: REF_TERNARY, value: 'B1:2' }
1711
- ], opts);
1712
- t.isTokens('=SUM(A:A$10,3:B$2)', [
1713
- { type: FX_PREFIX, value: '=' },
1714
- { type: FUNCTION, value: 'SUM' },
1715
- { type: OPERATOR, value: '(' },
1716
- { type: REF_TERNARY, value: 'A:A$10' },
1717
- { type: OPERATOR, value: ',' },
1718
- { type: REF_TERNARY, value: '3:B$2' },
1719
- { type: OPERATOR, value: ')' }
1720
- ], opts);
1721
- t.isTokens('$A$10:$12', [
1722
- { type: REF_TERNARY, value: '$A$10:$12' }
1723
- ], opts);
1724
- t.isTokens('1:D$1', [
1725
- { type: REF_TERNARY, value: '1:D$1' }
1726
- ], opts);
1727
- t.isTokens('=A1:IF()', [
1728
- { type: FX_PREFIX, value: '=' },
1729
- { type: REF_RANGE, value: 'A1' },
1730
- { type: OPERATOR, value: ':' },
1731
- { type: FUNCTION, value: 'IF' },
1732
- { type: OPERATOR, value: '(' },
1733
- { type: OPERATOR, value: ')' }
1734
- ], opts);
1735
- t.isTokens('=A1:F.DIST()', [
1736
- { type: FX_PREFIX, value: '=' },
1737
- { type: REF_RANGE, value: 'A1' },
1738
- { type: OPERATOR, value: ':' },
1739
- { type: FUNCTION, value: 'F.DIST' },
1740
- { type: OPERATOR, value: '(' },
1741
- { type: OPERATOR, value: ')' }
1742
- ], opts);
1743
- t.isTokens('=1:A1.', [
1744
- { type: FX_PREFIX, value: '=' },
1745
- { type: NUMBER, value: '1' },
1746
- { type: OPERATOR, value: ':' },
1747
- { type: REF_RANGE, value: 'A1' },
1748
- { type: UNKNOWN, value: '.' }
1749
- ], opts);
1750
- t.isTokens('=A1:X$', [
1751
- { type: FX_PREFIX, value: '=' },
1752
- { type: REF_RANGE, value: 'A1' },
1753
- { type: OPERATOR, value: ':' },
1754
- { type: UNKNOWN, value: 'X$' }
1755
- ], opts);
1756
-
1757
- t.isTokens('=[foo]Bar!A:A1', [
1758
- { type: FX_PREFIX, value: '=' },
1759
- { type: CONTEXT, value: '[foo]Bar' },
1760
- { type: OPERATOR, value: '!' },
1761
- { type: REF_TERNARY, value: 'A:A1' }
1762
- ], { mergeRefs: false, allowTernary: true });
1763
-
1764
- t.end();
1765
- });
1766
-
1767
- test('tokenize external refs syntax from XLSX files', t => {
1768
- const opts = { xlsx: true };
1769
- // Excel XLS files only use positive integers as workbooks...
1770
- t.isTokens('=[1]!A1', [
1771
- { type: FX_PREFIX, value: '=' },
1772
- { type: REF_RANGE, value: '[1]!A1' }
1773
- ], opts);
1774
- t.isTokens('=[1]Sheet1!A1', [
1775
- { type: FX_PREFIX, value: '=' },
1776
- { type: REF_RANGE, value: '[1]Sheet1!A1' }
1777
- ], opts);
1778
- t.isTokens('=[4]!name', [
1779
- { type: FX_PREFIX, value: '=' },
1780
- { type: REF_NAMED, value: '[4]!name' }
1781
- ], opts);
1782
- t.isTokens('=[16]Sheet1!name', [
1783
- { type: FX_PREFIX, value: '=' },
1784
- { type: REF_NAMED, value: '[16]Sheet1!name' }
1785
- ], opts);
1786
- t.isTokens("='[1]'!A1", [
1787
- { type: FX_PREFIX, value: '=' },
1788
- { type: REF_RANGE, value: "'[1]'!A1" }
1789
- ], opts);
1790
- t.isTokens("='[1]Sheet1'!A1", [
1791
- { type: FX_PREFIX, value: '=' },
1792
- { type: REF_RANGE, value: "'[1]Sheet1'!A1" }
1793
- ], opts);
1794
- t.isTokens("='[4]'!name", [
1795
- { type: FX_PREFIX, value: '=' },
1796
- { type: REF_NAMED, value: "'[4]'!name" }
1797
- ], opts);
1798
- t.isTokens("='[16]Sheet1'!name", [
1799
- { type: FX_PREFIX, value: '=' },
1800
- { type: REF_NAMED, value: "'[16]Sheet1'!name" }
1801
- ], opts);
1802
- // ...fx additionally permits workbook names
1803
- t.isTokens('=[Workbook.xlsx]!A1', [
1804
- { type: FX_PREFIX, value: '=' },
1805
- { type: REF_RANGE, value: '[Workbook.xlsx]!A1' }
1806
- ], opts);
1807
- t.isTokens('=[Workbook.xlsx]Sheet1!A1', [
1808
- { type: FX_PREFIX, value: '=' },
1809
- { type: REF_RANGE, value: '[Workbook.xlsx]Sheet1!A1' }
1810
- ], opts);
1811
- t.isTokens('=[Workbook.xlsx]!name', [
1812
- { type: FX_PREFIX, value: '=' },
1813
- { type: REF_NAMED, value: '[Workbook.xlsx]!name' }
1814
- ], opts);
1815
- t.isTokens('=[Workbook.xlsx]Sheet1!name', [
1816
- { type: FX_PREFIX, value: '=' },
1817
- { type: REF_NAMED, value: '[Workbook.xlsx]Sheet1!name' }
1818
- ], opts);
1819
- t.isTokens("='[Workbook.xlsx]'!A1", [
1820
- { type: FX_PREFIX, value: '=' },
1821
- { type: REF_RANGE, value: "'[Workbook.xlsx]'!A1" }
1822
- ], opts);
1823
- t.isTokens("='[Workbook.xlsx]Sheet1'!A1", [
1824
- { type: FX_PREFIX, value: '=' },
1825
- { type: REF_RANGE, value: "'[Workbook.xlsx]Sheet1'!A1" }
1826
- ], opts);
1827
- t.isTokens("='[Workbook.xlsx]'!name", [
1828
- { type: FX_PREFIX, value: '=' },
1829
- { type: REF_NAMED, value: "'[Workbook.xlsx]'!name" }
1830
- ], opts);
1831
- t.isTokens("='[Workbook.xlsx]Sheet1'!name", [
1832
- { type: FX_PREFIX, value: '=' },
1833
- { type: REF_NAMED, value: "'[Workbook.xlsx]Sheet1'!name" }
1834
- ], opts);
1835
-
1836
- t.end();
1837
- });
1838
-
1839
- test('tokenize r and c as names within LET and LAMBDA calls', t => {
1840
- t.isTokens('=c*(LAMBDA(r,c,r*c)+r)+r', [
1841
- { type: FX_PREFIX, value: '=' },
1842
- { type: UNKNOWN, value: 'c' },
1843
- { type: OPERATOR, value: '*' },
1844
- { type: OPERATOR, value: '(' },
1845
- { type: FUNCTION, value: 'LAMBDA' },
1846
- { type: OPERATOR, value: '(' },
1847
- { type: REF_NAMED, value: 'r' },
1848
- { type: OPERATOR, value: ',' },
1849
- { type: REF_NAMED, value: 'c' },
1850
- { type: OPERATOR, value: ',' },
1851
- { type: REF_NAMED, value: 'r' },
1852
- { type: OPERATOR, value: '*' },
1853
- { type: REF_NAMED, value: 'c' },
1854
- { type: OPERATOR, value: ')' },
1855
- { type: OPERATOR, value: '+' },
1856
- { type: UNKNOWN, value: 'r' },
1857
- { type: OPERATOR, value: ')' },
1858
- { type: OPERATOR, value: '+' },
1859
- { type: UNKNOWN, value: 'r' }
1860
- ]);
1861
- t.isTokens('=c*(LET(r,A1,c,B2,r*c)+r)+r', [
1862
- { type: FX_PREFIX, value: '=' },
1863
- { type: UNKNOWN, value: 'c' },
1864
- { type: OPERATOR, value: '*' },
1865
- { type: OPERATOR, value: '(' },
1866
- { type: FUNCTION, value: 'LET' },
1867
- { type: OPERATOR, value: '(' },
1868
- { type: REF_NAMED, value: 'r' },
1869
- { type: OPERATOR, value: ',' },
1870
- { type: REF_RANGE, value: 'A1' },
1871
- { type: OPERATOR, value: ',' },
1872
- { type: REF_NAMED, value: 'c' },
1873
- { type: OPERATOR, value: ',' },
1874
- { type: REF_RANGE, value: 'B2' },
1875
- { type: OPERATOR, value: ',' },
1876
- { type: REF_NAMED, value: 'r' },
1877
- { type: OPERATOR, value: '*' },
1878
- { type: REF_NAMED, value: 'c' },
1879
- { type: OPERATOR, value: ')' },
1880
- { type: OPERATOR, value: '+' },
1881
- { type: UNKNOWN, value: 'r' },
1882
- { type: OPERATOR, value: ')' },
1883
- { type: OPERATOR, value: '+' },
1884
- { type: UNKNOWN, value: 'r' }
1885
- ]);
1886
-
1887
- t.end();
1888
- });
1889
-
1890
- test('trim operators are not valid outside literal ranges', t => {
1891
- // when not merging refs, trim ops are allowed between ranges
1892
- t.isTokens('=Sheet1!A1.:.B2', [
1893
- { type: FX_PREFIX, value: '=' },
1894
- { type: CONTEXT, value: 'Sheet1' },
1895
- { type: OPERATOR, value: '!' },
1896
- { type: REF_RANGE, value: 'A1' },
1897
- { type: OPERATOR, value: '.:.' },
1898
- { type: REF_RANGE, value: 'B2' }
1899
- ], { mergeRefs: false });
1900
- t.isTokens('A1:.B2', [
1901
- { type: REF_RANGE, value: 'A1' },
1902
- { type: OPERATOR, value: ':.' },
1903
- { type: REF_RANGE, value: 'B2' }
1904
- ], { mergeRefs: false });
1905
- t.isTokens('A1.:B2', [
1906
- { type: REF_RANGE, value: 'A1' },
1907
- { type: OPERATOR, value: '.:' },
1908
- { type: REF_RANGE, value: 'B2' }
1909
- ], { mergeRefs: false });
1910
-
1911
- t.isTokens('=Sheet1!A.:.A.:.B.:.B', [
1912
- { type: FX_PREFIX, value: '=' },
1913
- { type: REF_BEAM, value: 'Sheet1!A.:.A' },
1914
- { type: UNKNOWN, value: '.:.' },
1915
- { type: REF_BEAM, value: 'B.:.B' }
1916
- ]);
1917
-
1918
- t.isTokens('=name1.:.name2', [
1919
- { type: FX_PREFIX, value: '=' },
1920
- { type: REF_NAMED, value: 'name1.' },
1921
- { type: UNKNOWN, value: ':.name2' }
1922
- ]);
1923
-
1924
- t.isTokens('=OFFSET(A1,1,1).:.INDIRECT("A1")', [
1925
- { type: FX_PREFIX, value: '=' },
1926
- { type: FUNCTION, value: 'OFFSET' },
1927
- { type: OPERATOR, value: '(' },
1928
- { type: REF_RANGE, value: 'A1' },
1929
- { type: OPERATOR, value: ',' },
1930
- { type: NUMBER, value: '1' },
1931
- { type: OPERATOR, value: ',' },
1932
- { type: NUMBER, value: '1' },
1933
- { type: OPERATOR, value: ')' },
1934
- { type: UNKNOWN, value: '.:.INDIRECT' },
1935
- { type: OPERATOR, value: '(' },
1936
- { type: STRING, value: '"A1"' },
1937
- { type: OPERATOR, value: ')' }
1938
- ]);
1939
- t.end();
1940
- });
1941
-
1942
- test('whitespace handling', t => {
1943
- t.isTokens('\tA1\u00a0+\nB2\r', [
1944
- { type: WHITESPACE, value: '\t' },
1945
- { type: REF_RANGE, value: 'A1' },
1946
- { type: WHITESPACE, value: '\u00a0' },
1947
- { type: OPERATOR, value: '+' },
1948
- { type: NEWLINE, value: '\n' },
1949
- { type: REF_RANGE, value: 'B2' },
1950
- { type: WHITESPACE, value: '\r' }
1951
- ]);
1952
- t.end();
1953
- });