@borgar/fx 4.12.0 → 4.13.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.
@@ -1,5 +1,14 @@
1
- const re_SRcolumnB = /^\[('['#@[\]]|[^'#@[\]])*\]/i;
2
- const re_SRcolumnN = /^([^#@[\]:]+)/i;
1
+ /* eslint-disable no-multi-spaces */
2
+ /* eslint-disable no-undefined */
3
+ import { isWS } from './lexers/lexWhitespace.js';
4
+
5
+ const AT = 64; // @
6
+ const BR_CLOSE = 93; // ]
7
+ const BR_OPEN = 91; // [
8
+ const COLON = 58; // :
9
+ const COMMA = 44; // ,
10
+ const HASH = 35; // #
11
+ const QUOT_SINGLE = 39; // '
3
12
 
4
13
  const keyTerms = {
5
14
  'headers': 1,
@@ -10,9 +19,8 @@ const keyTerms = {
10
19
  '@': 16
11
20
  };
12
21
 
13
- const fz = (...a) => Object.freeze(a);
14
-
15
22
  // only combinations allowed are: #data + (#headers | #totals | #data)
23
+ const fz = (...a) => Object.freeze(a);
16
24
  const sectionMap = {
17
25
  // no terms
18
26
  0: fz(),
@@ -28,140 +36,200 @@ const sectionMap = {
28
36
  6: fz('data', 'totals')
29
37
  };
30
38
 
31
- const matchColumn = (s, allowUnbraced = true) => {
32
- let m = re_SRcolumnB.exec(s);
33
- if (m) {
34
- const value = m[0].slice(1, -1).replace(/'(['#@[\]])/g, '$1');
35
- return [ m[0], value ];
39
+ function matchKeyword (str, pos) {
40
+ let p = pos;
41
+ if (str.charCodeAt(p++) !== BR_OPEN) {
42
+ return;
36
43
  }
37
- if (allowUnbraced) {
38
- m = re_SRcolumnN.exec(s);
39
- if (m) {
40
- return [ m[0], m[0] ];
44
+ if (str.charCodeAt(p++) !== HASH) {
45
+ return;
46
+ }
47
+ do {
48
+ const c = str.charCodeAt(p);
49
+ if (
50
+ (c >= 65 && c <= 90) || // A-Z
51
+ (c >= 97 && c <= 122) || // a-z
52
+ (c === 32) // space
53
+ ) {
54
+ p++;
55
+ }
56
+ else {
57
+ break;
41
58
  }
42
59
  }
43
- return null;
44
- };
60
+ while (p < pos + 11); // max length: '[#this row'
61
+ if (str.charCodeAt(p++) !== BR_CLOSE) {
62
+ return;
63
+ }
64
+ return p - pos;
65
+ }
45
66
 
46
- export function parseSRange (raw) {
47
- const columns = [];
48
- let pos = 0;
49
- let s = raw;
50
- let m;
51
- let m1;
52
- let terms = 0;
67
+ function skipWhitespace (str, pos) {
68
+ let p = pos;
69
+ while (isWS(str.charCodeAt(p))) { p++; }
70
+ return p - pos;
71
+ }
53
72
 
54
- // start of structured ref?
55
- if ((m = /^(\[\s*)/.exec(s))) {
56
- // quickly determine if this is a simple keyword or column
57
- // [#keyword]
58
- if ((m1 = /^\[#([a-z ]+)\]/i.exec(s))) {
59
- const k = m1[1].toLowerCase();
60
- pos += m1[0].length;
61
- if (keyTerms[k]) {
62
- terms |= keyTerms[k];
63
- }
64
- else {
65
- return null;
66
- }
67
- }
68
- // [column]
69
- else if ((m1 = matchColumn(s, false))) {
70
- pos += m1[0].length;
71
- if (m1[1]) {
72
- columns.push(m1[1]);
73
- }
74
- }
75
- // use the "normal" method
76
- // [[#keyword]]
77
- // [[column]]
78
- // [@]
79
- // [@column]
80
- // [@[column]]
81
- // [@column:column]
82
- // [@column:[column]]
83
- // [@[column]:column]
84
- // [@[column]:[column]]
85
- // [column:column]
86
- // [column:[column]]
87
- // [[column]:column]
88
- // [[column]:[column]]
89
- // [[#keyword],column]
90
- // [[#keyword],column:column]
91
- // [[#keyword],[#keyword],column:column]
92
- // ...
93
- else {
94
- let expect_more = true;
95
- s = s.slice(m[1].length);
96
- pos += m[1].length;
97
- // match keywords as we find them
98
- while (
99
- expect_more &&
100
- (m = /^\[#([a-z ]+)\](\s*,\s*)?/i.exec(s))
101
- ) {
102
- const k = m[1].toLowerCase();
103
- if (keyTerms[k]) {
104
- terms |= keyTerms[k];
105
- s = s.slice(m[0].length);
106
- pos += m[0].length;
107
- expect_more = !!m[2];
73
+ function matchColumn (str, pos, allowUnbraced = true) {
74
+ let p = pos;
75
+ let column = '';
76
+ if (str.charCodeAt(p) === BR_OPEN) {
77
+ p++;
78
+ let c;
79
+ do {
80
+ c = str.charCodeAt(p);
81
+ if (c === QUOT_SINGLE) {
82
+ p++;
83
+ c = str.charCodeAt(p);
84
+ // Allowed set: '#@[]
85
+ if (c === QUOT_SINGLE || c === HASH || c === AT || c === BR_OPEN || c === BR_CLOSE) {
86
+ column += String.fromCharCode(c);
87
+ p++;
108
88
  }
109
89
  else {
110
- return null;
90
+ return;
111
91
  }
112
92
  }
113
- // is there an @ specifier?
114
- if (expect_more && (m = /^@/.exec(s))) {
115
- terms |= keyTerms['@'];
116
- s = s.slice(1);
117
- pos += 1;
118
- expect_more = s[0] !== ']';
93
+ // Allowed set is all chars BUT: '#@[]
94
+ else if (c === QUOT_SINGLE || c === HASH || c === AT || c === BR_OPEN) {
95
+ return;
119
96
  }
120
- // not all keyword terms may be combined
121
- if (!(terms in sectionMap)) {
122
- return null;
97
+ else if (c === BR_CLOSE) {
98
+ p++;
99
+ return [ str.slice(pos, p), column ];
123
100
  }
124
- // column definitions
125
- const leftCol = expect_more ? matchColumn(raw.slice(pos)) : null;
126
- if (leftCol) {
127
- pos += leftCol[0].length;
128
- columns.push(leftCol[1]);
129
- s = raw.slice(pos);
130
- if (s[0] === ':') {
131
- s = s.slice(1);
132
- pos++;
133
- const rightCol = matchColumn(s);
134
- if (rightCol) {
135
- pos += rightCol[0].length;
136
- columns.push(rightCol[1]);
137
- }
138
- else {
139
- return null;
140
- }
141
- }
142
- expect_more = false;
101
+ else {
102
+ column += String.fromCharCode(c);
103
+ p++;
143
104
  }
144
- // advance ws
145
- while (raw[pos] === ' ') {
146
- pos++;
105
+ }
106
+ while (p < str.length);
107
+ }
108
+ else if (allowUnbraced) {
109
+ let c;
110
+ do {
111
+ c = str.charCodeAt(p);
112
+ // Allowed set is all chars BUT: '#@[]:
113
+ if (c === QUOT_SINGLE || c === HASH || c === AT || c === BR_OPEN || c === BR_CLOSE || c === COLON) {
114
+ break;
147
115
  }
148
- // close the ref
149
- if (expect_more || raw[pos] !== ']') {
150
- return null;
116
+ else {
117
+ column += String.fromCharCode(c);
118
+ p++;
151
119
  }
152
- // step over the closing ]
153
- pos++;
120
+ }
121
+ while (p < str.length);
122
+ if (p !== pos) {
123
+ return [ column, column ];
124
+ }
125
+ }
126
+ }
127
+
128
+ export function parseSRange (str, pos = 0) {
129
+ const columns = [];
130
+ const start = pos;
131
+ let m;
132
+ let terms = 0;
133
+
134
+ // structured refs start with a [
135
+ if (str.charCodeAt(pos) !== BR_OPEN) {
136
+ return;
137
+ }
138
+
139
+ // simple keyword: [#keyword]
140
+ if ((m = matchKeyword(str, pos))) {
141
+ const k = str.slice(pos + 2, pos + m - 1);
142
+ pos += m;
143
+ const term = keyTerms[k.toLowerCase()];
144
+ if (!term) { return; }
145
+ terms |= term;
146
+ }
147
+ // simple column: [column]
148
+ else if ((m = matchColumn(str, pos, false))) {
149
+ pos += m[0].length;
150
+ if (m[1]) {
151
+ columns.push(m[1]);
154
152
  }
155
153
  }
154
+ // use the "normal" method
155
+ // [[#keyword]]
156
+ // [[column]]
157
+ // [@]
158
+ // [@column]
159
+ // [@[column]]
160
+ // [@column:column]
161
+ // [@column:[column]]
162
+ // [@[column]:column]
163
+ // [@[column]:[column]]
164
+ // [column:column]
165
+ // [column:[column]]
166
+ // [[column]:column]
167
+ // [[column]:[column]]
168
+ // [[#keyword],column]
169
+ // [[#keyword],column:column]
170
+ // [[#keyword],[#keyword],column:column]
171
+ // ...
156
172
  else {
157
- return null;
173
+ let expect_more = true;
174
+ pos++; // skip open brace
175
+ pos += skipWhitespace(str, pos);
176
+ // match keywords as we find them
177
+ while (expect_more && (m = matchKeyword(str, pos))) {
178
+ const k = str.slice(pos + 2, pos + m - 1);
179
+ const term = keyTerms[k.toLowerCase()];
180
+ if (!term) { return; }
181
+ terms |= term;
182
+ pos += m;
183
+ pos += skipWhitespace(str, pos);
184
+ expect_more = str.charCodeAt(pos) === COMMA;
185
+ if (expect_more) {
186
+ pos++;
187
+ pos += skipWhitespace(str, pos);
188
+ }
189
+ }
190
+ // is there an @ specifier?
191
+ if (expect_more && (str.charCodeAt(pos) === AT)) {
192
+ terms |= keyTerms['@'];
193
+ pos += 1;
194
+ expect_more = str.charCodeAt(pos) !== BR_CLOSE;
195
+ }
196
+ // not all keyword terms may be combined
197
+ if (!sectionMap[terms]) {
198
+ return;
199
+ }
200
+ // column definitions
201
+ const leftCol = expect_more && matchColumn(str, pos, true);
202
+ if (leftCol) {
203
+ pos += leftCol[0].length;
204
+ columns.push(leftCol[1]);
205
+ if (str.charCodeAt(pos) === COLON) {
206
+ pos++;
207
+ const rightCol = matchColumn(str, pos, true);
208
+ if (rightCol) {
209
+ pos += rightCol[0].length;
210
+ columns.push(rightCol[1]);
211
+ }
212
+ else {
213
+ return;
214
+ }
215
+ }
216
+ expect_more = false;
217
+ }
218
+ // advance ws
219
+ pos += skipWhitespace(str, pos);
220
+ // close the ref
221
+ if (expect_more || str.charCodeAt(pos) !== BR_CLOSE) {
222
+ return;
223
+ }
224
+ // step over the closing ]
225
+ pos++;
158
226
  }
159
227
 
160
228
  const sections = sectionMap[terms];
161
229
  return {
162
230
  columns,
163
231
  sections: sections ? sections.concat() : sections,
164
- length: pos,
165
- token: raw.slice(0, pos)
232
+ length: pos - start,
233
+ token: str.slice(start, pos)
166
234
  };
167
235
  }
@@ -24,7 +24,7 @@ Test.prototype.isSREqual = function isSREqual (expr, expect, opts) {
24
24
  this.deepEqual(parseStructRef(expr, opts), expect, expr);
25
25
  };
26
26
 
27
- test.only('parse structured references', t => {
27
+ test('parse structured references', t => {
28
28
  t.isSREqual('table[col]', {
29
29
  table: 'table',
30
30
  columns: [ 'col' ]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@borgar/fx",
3
- "version": "4.12.0",
3
+ "version": "4.13.0",
4
4
  "description": "Utilities for working with Excel formulas",
5
5
  "main": "dist/fx.js",
6
6
  "types": "dist/fx.d.ts",
@@ -16,6 +16,7 @@
16
16
  "preversion": "npm test && npm run lint",
17
17
  "version": "npm run build",
18
18
  "lint": "eslint lib/*.js",
19
+ "benchmark": "node benchmark/benchmark.js",
19
20
  "test": "tape lib/*.spec.js | tap-min",
20
21
  "build:all": "npm run build:types && npm run build:docs && npm run build",
21
22
  "build:types": "jsdoc -c tsd.json lib>dist/fx.d.ts",
@@ -43,20 +44,21 @@
43
44
  "author": "Borgar Þorsteinsson <borgar@borgar.net> (http://borgar.net/)",
44
45
  "license": "MIT",
45
46
  "devDependencies": {
46
- "@babel/core": "~7.23.9",
47
- "@babel/eslint-parser": "~7.23.10",
48
- "@babel/preset-env": "~7.23.9",
47
+ "@babel/core": "~7.28.5",
48
+ "@babel/eslint-parser": "~7.28.5",
49
+ "@babel/preset-env": "~7.28.5",
49
50
  "@borgar/eslint-config": "~3.1.0",
50
- "@borgar/jsdoc-tsmd": "~0.2.1",
51
- "@rollup/plugin-babel": "~6.0.4",
51
+ "@borgar/jsdoc-tsmd": "~0.2.2",
52
+ "@rollup/plugin-babel": "~6.1.0",
52
53
  "@rollup/plugin-terser": "~0.4.4",
53
54
  "babel-eslint": "~10.1.0",
55
+ "benchmark": "~2.1.4",
54
56
  "eslint": "~8.56.0",
55
57
  "eslint-plugin-jsdoc": "~48.1.0",
56
- "jsdoc": "~4.0.2",
57
- "rollup": "~4.12.0",
58
+ "jsdoc": "~4.0.5",
59
+ "rollup": "~4.52.5",
58
60
  "tap-min": "~3.0.0",
59
- "tape": "~5.7.5",
60
- "typescript": "~5.3.3"
61
+ "tape": "~5.9.0",
62
+ "typescript": "~5.9.3"
61
63
  }
62
64
  }
package/lib/lexerParts.js DELETED
@@ -1,228 +0,0 @@
1
- import {
2
- OPERATOR,
3
- BOOLEAN,
4
- ERROR,
5
- NUMBER,
6
- FUNCTION,
7
- NEWLINE,
8
- WHITESPACE,
9
- STRING,
10
- CONTEXT,
11
- CONTEXT_QUOTE,
12
- REF_RANGE,
13
- REF_BEAM,
14
- REF_NAMED,
15
- REF_TERNARY,
16
- REF_STRUCT,
17
- MAX_COLS,
18
- MAX_ROWS,
19
- OPERATOR_TRIM
20
- } from './constants.js';
21
- import { fromCol } from './fromCol.js';
22
- import { parseSRange } from './parseSRange.js';
23
-
24
- const re_ERROR = /^#(NAME\?|FIELD!|CALC!|VALUE!|REF!|DIV\/0!|NULL!|NUM!|N\/A|GETTING_DATA\b|SPILL!|UNKNOWN!|FIELD\b|CALC\b|SYNTAX\?|ERROR!|CONNECT!|BLOCKED!|EXTERNAL!)/i;
25
- const re_OPERATOR = /^(<=|>=|<>|[-+/*^%&<>=]|[{},;]|[()]|@|:|!|#)/;
26
- const re_BOOLEAN = /^(TRUE|FALSE)\b/i;
27
- const re_FUNCTION = /^[A-Z_]+[A-Z\d_.]*(?=\()/i;
28
- const re_NEWLINE = /^\n+/;
29
- const re_WHITESPACE = /^[ \f\r\t\v\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]+/;
30
- const re_STRING = /^"(?:""|[^"])*("|$)/;
31
- const re_NUMBER = /^(?:\d+(\.\d+)?(?:[eE][+-]?\d+)?|\d+)/;
32
- const re_CONTEXT = /^(?!!)(\[(?:[^\]])+\])?([0-9A-Za-z._¡¤§¨ª\u00ad¯-\uffff]+)?(?=!)/;
33
- const re_CONTEXT_QUOTE = /^'(?:''|[^'])*('|$)(?=!)/;
34
- const re_RANGE_TRIM = /^(\.:\.|\.:|:\.)/;
35
-
36
- const rngPart = '\\$?[A-Z]{1,3}\\$?[1-9][0-9]{0,6}';
37
- const colPart = '\\$?[A-Z]{1,3}';
38
- const rowPart = '\\$?[1-9][0-9]{0,6}';
39
- const rangeOp = '\\.?:\\.?';
40
- const nextNotChar = '(?![a-z0-9_\\u00a1-\\uffff])';
41
- const re_A1COL = new RegExp(`^${colPart}${rangeOp}${colPart}${nextNotChar}`, 'i');
42
- const re_A1ROW = new RegExp(`^${rowPart}${rangeOp}${rowPart}${nextNotChar}`, 'i');
43
- const re_A1RANGE = new RegExp(`^${rngPart}${nextNotChar}`, 'i');
44
- const re_A1PARTIAL = new RegExp(`^((${colPart}|${rowPart})${rangeOp}${rngPart}|${rngPart}${rangeOp}(${colPart}|${rowPart}))(?![\\w($.])`, 'i');
45
- const rPart = '(?:R(?:\\[[+-]?\\d+\\]|[1-9][0-9]{0,6})?)';
46
- const cPart = '(?:C(?:\\[[+-]?\\d+\\]|[1-9][0-9]{0,4})?)';
47
- const re_RCCOL = new RegExp(`^${cPart}(${rangeOp}${cPart})?${nextNotChar}`, 'i');
48
- const re_RCROW = new RegExp(`^${rPart}(${rangeOp}${rPart})?${nextNotChar}`, 'i');
49
- const re_RCRANGE = new RegExp(`^(?:(?=[RC])${rPart}${cPart})${nextNotChar}`, 'i');
50
- const re_RCPARTIAL = new RegExp(`^(${rPart}${cPart}(${rangeOp}${cPart}|${rangeOp}${rPart})(?![[\\d])|(${rPart}|${cPart})(${rangeOp}${rPart}${cPart}))${nextNotChar}`, 'i');
51
-
52
- // The advertized named ranges rules are a bit off from what Excel seems to do:
53
- // in the "extended range" of chars, it looks like it allows most things above
54
- // U+00B0 with the range between U+00A0-U+00AF rather random.
55
- // eslint-disable-next-line
56
- // const re_NAMED = /^[a-zA-Z\\_¡¤§¨ª\u00ad¯\u00b0-\uffff][a-zA-Z0-9\\_.?¡¤§¨ª\u00ad¯\u00b0-\uffff]{0,254}/i;
57
- // I've simplified to allowing everything above U+00A1:
58
- const re_NAMED = /^[a-zA-Z\\_\u00a1-\uffff][a-zA-Z0-9\\_.?\u00a1-\uffff]{0,254}/i;
59
-
60
- function makeHandler (type, re) {
61
- return str => {
62
- const m = re.exec(str);
63
- if (m) {
64
- return { type: type, value: m[0] };
65
- }
66
- };
67
- }
68
-
69
- function lexNamed (str) {
70
- const m = re_NAMED.exec(str);
71
- if (m) {
72
- const lc = m[0].toLowerCase();
73
- // names starting with \ must be at least 3 char long
74
- if (lc[0] === '\\' && m[0].length < 3) {
75
- return null;
76
- }
77
- // single characters R and C are forbidden as names
78
- if (lc === 'r' || lc === 'c') {
79
- return null;
80
- }
81
- return { type: REF_NAMED, value: m[0] };
82
- }
83
- }
84
-
85
- const re_QUOTED_VALUE = /^'(?:[^[\]]+?)?(?:\[(.+?)\])?(?:[^[\]]+?)'$/;
86
- const re_QUOTED_VALUE_XLSX = /^'\[(.+?)\]'$/;
87
- function lexContext (str, options) {
88
- const mq = re_CONTEXT_QUOTE.exec(str);
89
- if (mq) {
90
- const value = mq[0];
91
- const isValid = options.xlsx
92
- ? re_QUOTED_VALUE_XLSX.test(value) || re_QUOTED_VALUE.test(value)
93
- : re_QUOTED_VALUE.test(value);
94
- if (isValid) {
95
- return { type: CONTEXT_QUOTE, value: value };
96
- }
97
- }
98
- // xlsx xml uses a variant of the syntax that has external references in
99
- // bracets. Any of: [1]Sheet1!A1, '[1]Sheet one'!A1, [1]!named
100
- // We're only concerned with the non quoted version here as the quoted version
101
- // doesn't currently examine what is in the quotes.
102
- const m = re_CONTEXT.exec(str);
103
- if (m) {
104
- const [ , a, b ] = m;
105
- const valid = (
106
- ((a && b) || b) || // "[a]b!" or "b!" forms
107
- (a && !b && options.xlsx) // "[a]" form (allowed in xlsx mode)
108
- );
109
- if (valid) {
110
- return { type: CONTEXT, value: m[0] };
111
- }
112
- }
113
- }
114
-
115
- function lexStructured (str) {
116
- const structData = parseSRange(str);
117
- if (structData) {
118
- // we have a match for a valid SR
119
- let i = structData.length;
120
- // skip tailing whitespace
121
- while (str[i] === ' ') {
122
- i++;
123
- }
124
- // and ensure that it isn't followed by a !
125
- if (str[i] !== '!') {
126
- return {
127
- type: REF_STRUCT,
128
- value: structData.token
129
- };
130
- }
131
- }
132
- return null;
133
- }
134
-
135
- const reRCNums = /([RC])(\[?)(-?\d+)/gi;
136
- const reA1Nums = /(\d+|[a-zA-Z]+)/gi;
137
- function lexRange (str, options) {
138
- let m, t;
139
- if (options.r1c1) {
140
- // RC notation
141
- if (options.allowTernary && (m = re_RCPARTIAL.exec(str))) {
142
- t = { type: REF_TERNARY, value: m[0] };
143
- }
144
- else if ((m = re_RCRANGE.exec(str))) {
145
- t = { type: REF_RANGE, value: m[0] };
146
- }
147
- else if ((m = re_RCROW.exec(str)) || (m = re_RCCOL.exec(str))) {
148
- t = { type: REF_BEAM, value: m[0] };
149
- }
150
- if (t) {
151
- reRCNums.lastIndex = 0;
152
- while ((m = reRCNums.exec(t.value)) !== null) {
153
- const x = (m[1] === 'R' ? MAX_ROWS : MAX_COLS) + (m[2] ? 0 : 1);
154
- const val = parseInt(m[3], 10);
155
- if (val > x || val < -x) {
156
- return null;
157
- }
158
- }
159
- return t;
160
- }
161
- }
162
- else {
163
- // A1 notation
164
- if (options.allowTernary && (m = re_A1PARTIAL.exec(str))) {
165
- t = { type: REF_TERNARY, value: m[0] };
166
- }
167
- else if ((m = re_A1COL.exec(str)) || (m = re_A1ROW.exec(str))) {
168
- t = { type: REF_BEAM, value: m[0] };
169
- }
170
- else if ((m = re_A1RANGE.exec(str))) {
171
- t = { type: REF_RANGE, value: m[0] };
172
- }
173
- if (t) {
174
- reA1Nums.lastIndex = 0;
175
- // XXX: can probably optimize this as we know letters can only be 3 at max
176
- while ((m = reA1Nums.exec(t.value)) !== null) {
177
- if (/^\d/.test(m[1])) { // row
178
- if ((parseInt(m[1], 10) - 1) > MAX_ROWS) {
179
- return null;
180
- }
181
- }
182
- else if (fromCol(m[1]) > MAX_COLS) {
183
- return null;
184
- }
185
- }
186
- return t;
187
- }
188
- }
189
- }
190
-
191
- function lexRefOp (s, opts) {
192
- // in R1C1 mode we only allow !
193
- if (opts.r1c1) {
194
- return (s[0] === '!')
195
- ? { type: OPERATOR, value: s[0] }
196
- : null;
197
- }
198
- // in A1 mode we allow [ '!', ':', '.:', ':.', '.:.']
199
- const m = /^(!|\.?:\.?)/.exec(s);
200
- if (m) {
201
- return { type: OPERATOR, value: m[1] };
202
- }
203
- return null;
204
- }
205
-
206
- export const lexers = [
207
- makeHandler(ERROR, re_ERROR),
208
- makeHandler(OPERATOR_TRIM, re_RANGE_TRIM),
209
- makeHandler(OPERATOR, re_OPERATOR),
210
- makeHandler(FUNCTION, re_FUNCTION),
211
- makeHandler(BOOLEAN, re_BOOLEAN),
212
- makeHandler(NEWLINE, re_NEWLINE),
213
- makeHandler(WHITESPACE, re_WHITESPACE),
214
- makeHandler(STRING, re_STRING),
215
- lexContext,
216
- lexRange,
217
- lexStructured,
218
- makeHandler(NUMBER, re_NUMBER),
219
- lexNamed
220
- ];
221
-
222
- export const lexersRefs = [
223
- lexRefOp,
224
- lexContext,
225
- lexRange,
226
- lexStructured,
227
- lexNamed
228
- ];