@borgar/fx 3.1.0 → 4.0.0-rc.2
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/.eslintrc +25 -12
- package/.jsdoc/config.json +17 -0
- package/.jsdoc/publish.js +195 -0
- package/README.md +8 -311
- package/dist/fx.js +1 -1
- package/docs/API.md +708 -0
- package/docs/AST format.md +144 -0
- package/docs/References.md +60 -0
- package/lib/a1.js +156 -30
- package/lib/a1.spec.js +9 -2
- package/lib/{addMeta.js → addTokenMeta.js} +50 -5
- package/lib/{addMeta.spec.js → addTokenMeta.spec.js} +16 -16
- package/lib/constants.js +14 -4
- package/lib/fixRanges.js +64 -10
- package/lib/fixRanges.spec.js +35 -6
- package/lib/index.js +105 -17
- package/lib/isType.js +119 -8
- package/lib/lexer-srefs.spec.js +311 -0
- package/lib/lexer.js +55 -15
- package/lib/lexer.spec.js +223 -214
- package/lib/lexerParts.js +38 -14
- package/lib/mergeRefTokens.js +38 -25
- package/lib/mergeRefTokens.spec.js +39 -39
- package/lib/parseRef.js +17 -12
- package/lib/parser.js +498 -0
- package/lib/parser.spec.js +777 -0
- package/lib/rc.js +95 -22
- package/lib/rc.spec.js +16 -5
- package/lib/sr.js +277 -0
- package/lib/sr.spec.js +179 -0
- package/lib/translate-toA1.spec.js +38 -20
- package/lib/translate-toRC.spec.js +23 -23
- package/lib/translate.js +111 -30
- package/package.json +3 -1
- package/References.md +0 -39
package/lib/lexerParts.js
CHANGED
|
@@ -9,14 +9,16 @@ import {
|
|
|
9
9
|
STRING,
|
|
10
10
|
CONTEXT,
|
|
11
11
|
CONTEXT_QUOTE,
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
REF_RANGE,
|
|
13
|
+
REF_BEAM,
|
|
14
|
+
REF_NAMED,
|
|
15
|
+
REF_TERNARY,
|
|
16
|
+
REF_STRUCT,
|
|
16
17
|
MAX_COLS,
|
|
17
18
|
MAX_ROWS
|
|
18
19
|
} from './constants.js';
|
|
19
20
|
import { fromCol } from './a1.js';
|
|
21
|
+
import { parseSRange } from './sr.js';
|
|
20
22
|
|
|
21
23
|
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;
|
|
22
24
|
const re_OPERATOR = /^(<=|>=|<>|[-+/*^%&<>=]|[{},;]|[()]|@|:|!|#)/;
|
|
@@ -50,7 +52,7 @@ const re_RCPARTIAL = new RegExp(`^(${rPart}${cPart}(:${cPart}|:${rPart})(?![[\\d
|
|
|
50
52
|
// eslint-disable-next-line
|
|
51
53
|
// const re_NAMED = /^[a-zA-Z\\_¡¤§¨ª\u00ad¯\u00b0-\uffff][a-zA-Z0-9\\_.?¡¤§¨ª\u00ad¯\u00b0-\uffff]{0,254}/i;
|
|
52
54
|
// I've simplified to allowing everything above U+00A1:
|
|
53
|
-
const re_NAMED = /^[a-zA-Z\\_\u00a1-\uffff][a-zA-Z0-9\\_.?\u00a1-\uffff]{0,254}/i;
|
|
55
|
+
const re_NAMED = /^(?![CR]\b)[a-zA-Z\\_\u00a1-\uffff][a-zA-Z0-9\\_.?\u00a1-\uffff]{0,254}/i;
|
|
54
56
|
|
|
55
57
|
function makeHandler (type, re) {
|
|
56
58
|
return str => {
|
|
@@ -61,6 +63,26 @@ function makeHandler (type, re) {
|
|
|
61
63
|
};
|
|
62
64
|
}
|
|
63
65
|
|
|
66
|
+
function lexStructured (str) {
|
|
67
|
+
const structData = parseSRange(str);
|
|
68
|
+
if (structData) {
|
|
69
|
+
// we have a match for a valid SR
|
|
70
|
+
let i = structData.length;
|
|
71
|
+
// skip tailing whitespace
|
|
72
|
+
while (str[i] === ' ') {
|
|
73
|
+
i++;
|
|
74
|
+
}
|
|
75
|
+
// and ensure that it isn't followed by a !
|
|
76
|
+
if (str[i] !== '!') {
|
|
77
|
+
return {
|
|
78
|
+
type: REF_STRUCT,
|
|
79
|
+
value: structData.token
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
|
|
64
86
|
const reRCNums = /([RC])(\[?)(-?\d+)/gi;
|
|
65
87
|
const reA1Nums = /(\d+|[a-zA-Z]+)/gi;
|
|
66
88
|
function lexRange (str, options) {
|
|
@@ -68,13 +90,13 @@ function lexRange (str, options) {
|
|
|
68
90
|
if (options.r1c1) {
|
|
69
91
|
// RC notation
|
|
70
92
|
if (options.allowTernary && (m = re_RCPARTIAL.exec(str))) {
|
|
71
|
-
t = { type:
|
|
93
|
+
t = { type: REF_TERNARY, value: m[0] };
|
|
72
94
|
}
|
|
73
95
|
else if ((m = re_RCRANGE.exec(str))) {
|
|
74
|
-
t = { type:
|
|
96
|
+
t = { type: REF_RANGE, value: m[0] };
|
|
75
97
|
}
|
|
76
98
|
else if ((m = re_RCROW.exec(str)) || (m = re_RCCOL.exec(str))) {
|
|
77
|
-
t = { type:
|
|
99
|
+
t = { type: REF_BEAM, value: m[0] };
|
|
78
100
|
}
|
|
79
101
|
if (t) {
|
|
80
102
|
reRCNums.lastIndex = 0;
|
|
@@ -91,13 +113,13 @@ function lexRange (str, options) {
|
|
|
91
113
|
else {
|
|
92
114
|
// A1 notation
|
|
93
115
|
if (options.allowTernary && (m = re_A1PARTIAL.exec(str))) {
|
|
94
|
-
t = { type:
|
|
116
|
+
t = { type: REF_TERNARY, value: m[0] };
|
|
95
117
|
}
|
|
96
118
|
else if ((m = re_A1COL.exec(str)) || (m = re_A1ROW.exec(str))) {
|
|
97
|
-
t = { type:
|
|
119
|
+
t = { type: REF_BEAM, value: m[0] };
|
|
98
120
|
}
|
|
99
121
|
else if ((m = re_A1RANGE.exec(str))) {
|
|
100
|
-
t = { type:
|
|
122
|
+
t = { type: REF_RANGE, value: m[0] };
|
|
101
123
|
}
|
|
102
124
|
if (t) {
|
|
103
125
|
reA1Nums.lastIndex = 0;
|
|
@@ -117,7 +139,7 @@ function lexRange (str, options) {
|
|
|
117
139
|
}
|
|
118
140
|
|
|
119
141
|
function lexRefOp (s, opts) {
|
|
120
|
-
// in
|
|
142
|
+
// in R1C1 mode we only allow !
|
|
121
143
|
if (opts.r1c1) {
|
|
122
144
|
return (s[0] === '!')
|
|
123
145
|
? { type: OPERATOR, value: s[0] }
|
|
@@ -140,8 +162,9 @@ export const lexers = [
|
|
|
140
162
|
makeHandler(CONTEXT_QUOTE, re_CONTEXT_QUOTE),
|
|
141
163
|
makeHandler(CONTEXT, re_CONTEXT),
|
|
142
164
|
lexRange,
|
|
165
|
+
lexStructured,
|
|
143
166
|
makeHandler(NUMBER, re_NUMBER),
|
|
144
|
-
makeHandler(
|
|
167
|
+
makeHandler(REF_NAMED, re_NAMED)
|
|
145
168
|
];
|
|
146
169
|
|
|
147
170
|
export const lexersRefs = [
|
|
@@ -149,5 +172,6 @@ export const lexersRefs = [
|
|
|
149
172
|
makeHandler(CONTEXT_QUOTE, re_CONTEXT_QUOTE),
|
|
150
173
|
makeHandler(CONTEXT, re_CONTEXT),
|
|
151
174
|
lexRange,
|
|
152
|
-
|
|
175
|
+
lexStructured,
|
|
176
|
+
makeHandler(REF_NAMED, re_NAMED)
|
|
153
177
|
];
|
package/lib/mergeRefTokens.js
CHANGED
|
@@ -1,23 +1,27 @@
|
|
|
1
|
-
import { CONTEXT, CONTEXT_QUOTE,
|
|
1
|
+
import { CONTEXT, CONTEXT_QUOTE, REF_RANGE, REF_NAMED, REF_BEAM, REF_TERNARY, OPERATOR, REF_STRUCT } from './constants.js';
|
|
2
2
|
|
|
3
3
|
const END = '$';
|
|
4
4
|
|
|
5
5
|
const validRunsMerge = [
|
|
6
|
-
[
|
|
7
|
-
[
|
|
8
|
-
[
|
|
9
|
-
[
|
|
10
|
-
[ CONTEXT, '!',
|
|
11
|
-
[ CONTEXT, '!',
|
|
12
|
-
[ CONTEXT, '!',
|
|
13
|
-
[ CONTEXT, '!',
|
|
14
|
-
[ CONTEXT_QUOTE, '!',
|
|
15
|
-
[ CONTEXT_QUOTE, '!',
|
|
16
|
-
[ CONTEXT_QUOTE, '!',
|
|
17
|
-
[ CONTEXT_QUOTE, '!',
|
|
18
|
-
[
|
|
19
|
-
[ CONTEXT, '!',
|
|
20
|
-
[ CONTEXT_QUOTE, '!',
|
|
6
|
+
[ REF_RANGE, ':', REF_RANGE ],
|
|
7
|
+
[ REF_RANGE ],
|
|
8
|
+
[ REF_BEAM ],
|
|
9
|
+
[ REF_TERNARY ],
|
|
10
|
+
[ CONTEXT, '!', REF_RANGE, ':', REF_RANGE ],
|
|
11
|
+
[ CONTEXT, '!', REF_RANGE ],
|
|
12
|
+
[ CONTEXT, '!', REF_BEAM ],
|
|
13
|
+
[ CONTEXT, '!', REF_TERNARY ],
|
|
14
|
+
[ CONTEXT_QUOTE, '!', REF_RANGE, ':', REF_RANGE ],
|
|
15
|
+
[ CONTEXT_QUOTE, '!', REF_RANGE ],
|
|
16
|
+
[ CONTEXT_QUOTE, '!', REF_BEAM ],
|
|
17
|
+
[ CONTEXT_QUOTE, '!', REF_TERNARY ],
|
|
18
|
+
[ REF_NAMED ],
|
|
19
|
+
[ CONTEXT, '!', REF_NAMED ],
|
|
20
|
+
[ CONTEXT_QUOTE, '!', REF_NAMED ],
|
|
21
|
+
[ REF_STRUCT ],
|
|
22
|
+
[ REF_NAMED, REF_STRUCT ],
|
|
23
|
+
[ CONTEXT, '!', REF_NAMED, REF_STRUCT ],
|
|
24
|
+
[ CONTEXT_QUOTE, '!', REF_NAMED, REF_STRUCT ]
|
|
21
25
|
];
|
|
22
26
|
|
|
23
27
|
// valid token runs are converted to a tree structure
|
|
@@ -52,22 +56,31 @@ const matcher = (tokens, currNode, anchorIndex, index = 0) => {
|
|
|
52
56
|
return 0;
|
|
53
57
|
};
|
|
54
58
|
|
|
55
|
-
|
|
56
|
-
|
|
59
|
+
/**
|
|
60
|
+
* Merges context with reference tokens as possible in a list of tokens.
|
|
61
|
+
*
|
|
62
|
+
* When given a tokenlist, this function returns a new list with ranges returned
|
|
63
|
+
* as whole references (`Sheet1!A1:B2`) rather than separate tokens for each
|
|
64
|
+
* part: (`Sheet1`,`!`,`A1`,`:`,`B2`).
|
|
65
|
+
*
|
|
66
|
+
* @param {Array<Object>} tokenlist An array of tokens (from `tokenize()`)
|
|
67
|
+
* @return {Array} A new list of tokens with range parts merged.
|
|
68
|
+
*/
|
|
69
|
+
export function mergeRefTokens (tokenlist) {
|
|
57
70
|
const finalTokens = [];
|
|
58
71
|
// this seeks backwards because it's really the range part
|
|
59
72
|
// that controls what can be joined.
|
|
60
|
-
for (let i =
|
|
61
|
-
let token =
|
|
62
|
-
const valid = matcher(
|
|
73
|
+
for (let i = tokenlist.length - 1; i >= 0; i--) {
|
|
74
|
+
let token = tokenlist[i];
|
|
75
|
+
const valid = matcher(tokenlist, refPartsTree, i);
|
|
63
76
|
if (valid) {
|
|
64
|
-
const toMerge =
|
|
77
|
+
const toMerge = tokenlist.slice(i - valid + 1, i + 1);
|
|
65
78
|
// use the meta properties from the "first" token (right-most token)
|
|
66
79
|
token = { ...token };
|
|
67
80
|
token.value = toMerge.map(d => d.value).join('');
|
|
68
|
-
// adjust the
|
|
69
|
-
if (token.
|
|
70
|
-
token.
|
|
81
|
+
// adjust the offsets to include all the text
|
|
82
|
+
if (token.loc && toMerge[0].loc) {
|
|
83
|
+
token.loc[0] = toMerge[0].loc[0];
|
|
71
84
|
}
|
|
72
85
|
i -= valid - 1;
|
|
73
86
|
}
|
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
import { CONTEXT, FUNCTION, FX_PREFIX, OPERATOR,
|
|
1
|
+
import { CONTEXT, FUNCTION, FX_PREFIX, OPERATOR, REF_RANGE, REF_BEAM, REF_NAMED, REF_TERNARY, UNKNOWN } from './constants.js';
|
|
2
2
|
import { test } from 'tape';
|
|
3
3
|
import { mergeRefTokens } from './mergeRefTokens.js';
|
|
4
4
|
import { tokenize } from './lexer.js';
|
|
5
5
|
|
|
6
6
|
test('mergeRefTokens basics', t => {
|
|
7
|
-
const list = tokenize('=SUM([Wb1]Sheet1!A1:B2)', {
|
|
7
|
+
const list = tokenize('=SUM([Wb1]Sheet1!A1:B2)', { mergeRefs: false, withLocation: true });
|
|
8
8
|
|
|
9
9
|
t.deepEqual(list, [
|
|
10
|
-
{ type: FX_PREFIX, value: '=',
|
|
11
|
-
{ type: FUNCTION, value: 'SUM',
|
|
12
|
-
{ type: OPERATOR, value: '(',
|
|
10
|
+
{ type: FX_PREFIX, value: '=', loc: [ 0, 1 ] },
|
|
11
|
+
{ type: FUNCTION, value: 'SUM', loc: [ 1, 4 ] },
|
|
12
|
+
{ type: OPERATOR, value: '(', loc: [ 4, 5 ] },
|
|
13
13
|
|
|
14
|
-
{ type: CONTEXT, value: '[Wb1]Sheet1',
|
|
15
|
-
{ type: OPERATOR, value: '!',
|
|
16
|
-
{ type:
|
|
17
|
-
{ type: OPERATOR, value: ':',
|
|
18
|
-
{ type:
|
|
14
|
+
{ type: CONTEXT, value: '[Wb1]Sheet1', loc: [ 5, 16 ] },
|
|
15
|
+
{ type: OPERATOR, value: '!', loc: [ 16, 17 ] },
|
|
16
|
+
{ type: REF_RANGE, value: 'A1', loc: [ 17, 19 ] },
|
|
17
|
+
{ type: OPERATOR, value: ':', loc: [ 19, 20 ] },
|
|
18
|
+
{ type: REF_RANGE, value: 'B2', loc: [ 20, 22 ] },
|
|
19
19
|
|
|
20
|
-
{ type: OPERATOR, value: ')',
|
|
20
|
+
{ type: OPERATOR, value: ')', loc: [ 22, 23 ] }
|
|
21
21
|
]);
|
|
22
22
|
|
|
23
23
|
// set IDs on all tokens about to be joined
|
|
@@ -29,89 +29,89 @@ test('mergeRefTokens basics', t => {
|
|
|
29
29
|
|
|
30
30
|
const mergedList = mergeRefTokens(list);
|
|
31
31
|
t.deepEqual(mergedList, [
|
|
32
|
-
{ type: FX_PREFIX, value: '=',
|
|
33
|
-
{ type: FUNCTION, value: 'SUM',
|
|
34
|
-
{ type: OPERATOR, value: '(',
|
|
35
|
-
{ type:
|
|
32
|
+
{ type: FX_PREFIX, value: '=', loc: [ 0, 1 ] },
|
|
33
|
+
{ type: FUNCTION, value: 'SUM', loc: [ 1, 4 ] },
|
|
34
|
+
{ type: OPERATOR, value: '(', loc: [ 4, 5 ] },
|
|
35
|
+
{ type: REF_RANGE,
|
|
36
36
|
id: 'id5', // token has the id of the first one
|
|
37
37
|
value: '[Wb1]Sheet1!A1:B2',
|
|
38
|
-
|
|
39
|
-
{ type: OPERATOR, value: ')',
|
|
38
|
+
loc: [ 5, 22 ] },
|
|
39
|
+
{ type: OPERATOR, value: ')', loc: [ 22, 23 ] }
|
|
40
40
|
]);
|
|
41
41
|
|
|
42
42
|
t.end();
|
|
43
43
|
});
|
|
44
44
|
|
|
45
45
|
test('mergeRefTokens cases', t => {
|
|
46
|
-
const opts = {
|
|
46
|
+
const opts = { mergeRefs: true, allowTernary: true };
|
|
47
47
|
t.deepEqual(tokenize('A1', opts), [
|
|
48
|
-
{ type:
|
|
48
|
+
{ type: REF_RANGE, value: 'A1' }
|
|
49
49
|
]);
|
|
50
50
|
t.deepEqual(tokenize('A1:A1', opts), [
|
|
51
|
-
{ type:
|
|
51
|
+
{ type: REF_RANGE, value: 'A1:A1' }
|
|
52
52
|
]);
|
|
53
53
|
t.deepEqual(tokenize('A:A', opts), [
|
|
54
|
-
{ type:
|
|
54
|
+
{ type: REF_BEAM, value: 'A:A' }
|
|
55
55
|
]);
|
|
56
56
|
t.deepEqual(tokenize('A1:A', opts), [
|
|
57
|
-
{ type:
|
|
57
|
+
{ type: REF_TERNARY, value: 'A1:A' }
|
|
58
58
|
]);
|
|
59
59
|
|
|
60
60
|
t.deepEqual(tokenize('\'Sheet1\'!A1', opts), [
|
|
61
|
-
{ type:
|
|
61
|
+
{ type: REF_RANGE, value: '\'Sheet1\'!A1' }
|
|
62
62
|
]);
|
|
63
63
|
t.deepEqual(tokenize('\'Sheet1\'!A:A', opts), [
|
|
64
|
-
{ type:
|
|
64
|
+
{ type: REF_BEAM, value: '\'Sheet1\'!A:A' }
|
|
65
65
|
]);
|
|
66
66
|
t.deepEqual(tokenize('\'Sheet1\'!A1:A', opts), [
|
|
67
|
-
{ type:
|
|
67
|
+
{ type: REF_TERNARY, value: '\'Sheet1\'!A1:A' }
|
|
68
68
|
]);
|
|
69
69
|
t.deepEqual(tokenize('\'Sheet1\'!A1:A', opts), [
|
|
70
|
-
{ type:
|
|
70
|
+
{ type: REF_TERNARY, value: '\'Sheet1\'!A1:A' }
|
|
71
71
|
]);
|
|
72
72
|
|
|
73
73
|
t.deepEqual(tokenize('Sheet1!A1', opts), [
|
|
74
|
-
{ type:
|
|
74
|
+
{ type: REF_RANGE, value: 'Sheet1!A1' }
|
|
75
75
|
]);
|
|
76
76
|
t.deepEqual(tokenize('Sheet1!A:A', opts), [
|
|
77
|
-
{ type:
|
|
77
|
+
{ type: REF_BEAM, value: 'Sheet1!A:A' }
|
|
78
78
|
]);
|
|
79
79
|
t.deepEqual(tokenize('Sheet1!A1:A', opts), [
|
|
80
|
-
{ type:
|
|
80
|
+
{ type: REF_TERNARY, value: 'Sheet1!A1:A' }
|
|
81
81
|
]);
|
|
82
82
|
t.deepEqual(tokenize('Sheet1!A1:A', opts), [
|
|
83
|
-
{ type:
|
|
83
|
+
{ type: REF_TERNARY, value: 'Sheet1!A1:A' }
|
|
84
84
|
]);
|
|
85
85
|
|
|
86
86
|
t.deepEqual(tokenize('[WB]Sheet1!A1', opts), [
|
|
87
|
-
{ type:
|
|
87
|
+
{ type: REF_RANGE, value: '[WB]Sheet1!A1' }
|
|
88
88
|
]);
|
|
89
89
|
t.deepEqual(tokenize('[WB]Sheet1!A:A', opts), [
|
|
90
|
-
{ type:
|
|
90
|
+
{ type: REF_BEAM, value: '[WB]Sheet1!A:A' }
|
|
91
91
|
]);
|
|
92
92
|
t.deepEqual(tokenize('[WB]Sheet1!A1:A', opts), [
|
|
93
|
-
{ type:
|
|
93
|
+
{ type: REF_TERNARY, value: '[WB]Sheet1!A1:A' }
|
|
94
94
|
]);
|
|
95
95
|
t.deepEqual(tokenize('[WB]Sheet1!A1:A', opts), [
|
|
96
|
-
{ type:
|
|
96
|
+
{ type: REF_TERNARY, value: '[WB]Sheet1!A1:A' }
|
|
97
97
|
]);
|
|
98
98
|
|
|
99
99
|
t.deepEqual(tokenize('foo', opts), [
|
|
100
|
-
{ type:
|
|
100
|
+
{ type: REF_NAMED, value: 'foo' }
|
|
101
101
|
]);
|
|
102
102
|
t.deepEqual(tokenize('\'quoted\'!foo', opts), [
|
|
103
|
-
{ type:
|
|
103
|
+
{ type: REF_NAMED, value: '\'quoted\'!foo' }
|
|
104
104
|
]);
|
|
105
105
|
t.deepEqual(tokenize('Sheet1!foo', opts), [
|
|
106
|
-
{ type:
|
|
106
|
+
{ type: REF_NAMED, value: 'Sheet1!foo' }
|
|
107
107
|
]);
|
|
108
108
|
t.deepEqual(tokenize('[path]!foo', opts), [
|
|
109
109
|
{ type: UNKNOWN, value: '[path]' },
|
|
110
110
|
{ type: OPERATOR, value: '!' },
|
|
111
|
-
{ type:
|
|
111
|
+
{ type: REF_NAMED, value: 'foo' }
|
|
112
112
|
]);
|
|
113
113
|
t.deepEqual(tokenize('[path]prefix!foo', opts), [
|
|
114
|
-
{ type:
|
|
114
|
+
{ type: REF_NAMED, value: '[path]prefix!foo' }
|
|
115
115
|
]);
|
|
116
116
|
|
|
117
117
|
t.end();
|
package/lib/parseRef.js
CHANGED
|
@@ -2,10 +2,11 @@ import {
|
|
|
2
2
|
FX_PREFIX,
|
|
3
3
|
CONTEXT,
|
|
4
4
|
CONTEXT_QUOTE,
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
REF_RANGE,
|
|
6
|
+
REF_TERNARY,
|
|
7
|
+
REF_NAMED,
|
|
8
|
+
REF_BEAM,
|
|
9
|
+
REF_STRUCT,
|
|
9
10
|
OPERATOR
|
|
10
11
|
} from './constants.js';
|
|
11
12
|
import { lexersRefs } from './lexerParts.js';
|
|
@@ -23,16 +24,17 @@ function splitContext (contextString) {
|
|
|
23
24
|
const unquote = d => d.slice(1, -1).replace(/''/g, "'");
|
|
24
25
|
|
|
25
26
|
const pRangeOp = t => t && t.value === ':' && {};
|
|
26
|
-
const pRange = t => t && t.type ===
|
|
27
|
-
const pPartial = t => t && t.type ===
|
|
28
|
-
const pRange2 = t => t && t.type ===
|
|
27
|
+
const pRange = t => t && t.type === REF_RANGE && { r0: t.value };
|
|
28
|
+
const pPartial = t => t && t.type === REF_TERNARY && { r0: t.value };
|
|
29
|
+
const pRange2 = t => t && t.type === REF_RANGE && { r1: t.value };
|
|
29
30
|
const pBang = t => t && t.type === OPERATOR && t.value === '!' && {};
|
|
30
|
-
const pBeam = t => t && t.type ===
|
|
31
|
+
const pBeam = t => t && t.type === REF_BEAM && { r0: t.value };
|
|
32
|
+
const pStrucured = t => t && t.type === REF_STRUCT && { struct: t.value };
|
|
31
33
|
const pContext = t => {
|
|
32
34
|
if (t && t.type === CONTEXT) { return splitContext(t.value); }
|
|
33
35
|
if (t && t.type === CONTEXT_QUOTE) { return splitContext(unquote(t.value)); }
|
|
34
36
|
};
|
|
35
|
-
const pNamed = t => t && t.type ===
|
|
37
|
+
const pNamed = t => t && t.type === REF_NAMED && { name: t.value };
|
|
36
38
|
|
|
37
39
|
const validRuns = [
|
|
38
40
|
[ pPartial ],
|
|
@@ -47,13 +49,16 @@ const validRuns = [
|
|
|
47
49
|
|
|
48
50
|
const validRunsNamed = validRuns.concat([
|
|
49
51
|
[ pNamed ],
|
|
50
|
-
[ pContext, pBang, pNamed ]
|
|
52
|
+
[ pContext, pBang, pNamed ],
|
|
53
|
+
[ pStrucured ],
|
|
54
|
+
[ pNamed, pStrucured ],
|
|
55
|
+
[ pContext, pBang, pNamed, pStrucured ]
|
|
51
56
|
]);
|
|
52
57
|
|
|
53
58
|
export function parseRef (ref, opts) {
|
|
54
59
|
const options = {
|
|
55
|
-
|
|
56
|
-
|
|
60
|
+
withLocation: false,
|
|
61
|
+
mergeRefs: false,
|
|
57
62
|
allowTernary: false,
|
|
58
63
|
allowNamed: true,
|
|
59
64
|
r1c1: false,
|