@gridsheet/react-core 0.12.3 → 0.12.4-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/Cell.d.ts.map +1 -1
- package/dist/components/Cell.js +200 -181
- package/dist/components/Cell.js.map +1 -1
- package/dist/components/ContextMenu.js +211 -194
- package/dist/components/ContextMenu.js.map +1 -1
- package/dist/components/Editor.js +280 -263
- package/dist/components/Editor.js.map +1 -1
- package/dist/components/Emitter.js +41 -24
- package/dist/components/Emitter.js.map +1 -1
- package/dist/components/GridSheet.d.ts.map +1 -1
- package/dist/components/GridSheet.js +142 -105
- package/dist/components/GridSheet.js.map +1 -1
- package/dist/components/HeaderLeftCell.js +76 -60
- package/dist/components/HeaderLeftCell.js.map +1 -1
- package/dist/components/HeaderTopCell.js +77 -61
- package/dist/components/HeaderTopCell.js.map +1 -1
- package/dist/components/Resizer.d.ts.map +1 -1
- package/dist/components/Resizer.js +94 -75
- package/dist/components/Resizer.js.map +1 -1
- package/dist/components/SearchBox.d.ts.map +1 -1
- package/dist/components/SearchBox.js +68 -49
- package/dist/components/SearchBox.js.map +1 -1
- package/dist/components/StoreInitializer.js +83 -66
- package/dist/components/StoreInitializer.js.map +1 -1
- package/dist/components/Tabular.js +98 -80
- package/dist/components/Tabular.js.map +1 -1
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +36 -19
- package/dist/constants.js.map +1 -1
- package/dist/formula/evaluator.js +500 -474
- package/dist/formula/evaluator.js.map +1 -1
- package/dist/formula/functions/__base.js +27 -13
- package/dist/formula/functions/__base.js.map +1 -1
- package/dist/formula/functions/__utils.js +113 -95
- package/dist/formula/functions/__utils.js.map +1 -1
- package/dist/formula/functions/abs.js +31 -17
- package/dist/formula/functions/abs.js.map +1 -1
- package/dist/formula/functions/abs.spec.js +35 -23
- package/dist/formula/functions/abs.spec.js.map +1 -1
- package/dist/formula/functions/acos.js +38 -24
- package/dist/formula/functions/acos.js.map +1 -1
- package/dist/formula/functions/add.js +57 -43
- package/dist/formula/functions/add.js.map +1 -1
- package/dist/formula/functions/and.js +38 -24
- package/dist/formula/functions/and.js.map +1 -1
- package/dist/formula/functions/asin.js +38 -24
- package/dist/formula/functions/asin.js.map +1 -1
- package/dist/formula/functions/atan.js +36 -22
- package/dist/formula/functions/atan.js.map +1 -1
- package/dist/formula/functions/atan2.js +42 -28
- package/dist/formula/functions/atan2.js.map +1 -1
- package/dist/formula/functions/average.js +50 -36
- package/dist/formula/functions/average.js.map +1 -1
- package/dist/formula/functions/col.js +38 -24
- package/dist/formula/functions/col.js.map +1 -1
- package/dist/formula/functions/concat.js +37 -23
- package/dist/formula/functions/concat.js.map +1 -1
- package/dist/formula/functions/concatenate.js +35 -21
- package/dist/formula/functions/concatenate.js.map +1 -1
- package/dist/formula/functions/cos.js +36 -22
- package/dist/formula/functions/cos.js.map +1 -1
- package/dist/formula/functions/count.js +45 -31
- package/dist/formula/functions/count.js.map +1 -1
- package/dist/formula/functions/counta.js +45 -31
- package/dist/formula/functions/counta.js.map +1 -1
- package/dist/formula/functions/countif.js +40 -26
- package/dist/formula/functions/countif.js.map +1 -1
- package/dist/formula/functions/divide.js +42 -28
- package/dist/formula/functions/divide.js.map +1 -1
- package/dist/formula/functions/eq.js +35 -21
- package/dist/formula/functions/eq.js.map +1 -1
- package/dist/formula/functions/exp.js +38 -24
- package/dist/formula/functions/exp.js.map +1 -1
- package/dist/formula/functions/gt.js +37 -23
- package/dist/formula/functions/gt.js.map +1 -1
- package/dist/formula/functions/gte.js +37 -23
- package/dist/formula/functions/gte.js.map +1 -1
- package/dist/formula/functions/hlookup.js +77 -63
- package/dist/formula/functions/hlookup.js.map +1 -1
- package/dist/formula/functions/if.js +46 -32
- package/dist/formula/functions/if.js.map +1 -1
- package/dist/formula/functions/iferror.js +48 -34
- package/dist/formula/functions/iferror.js.map +1 -1
- package/dist/formula/functions/iferror.spec.js +63 -51
- package/dist/formula/functions/iferror.spec.js.map +1 -1
- package/dist/formula/functions/len.js +36 -22
- package/dist/formula/functions/len.js.map +1 -1
- package/dist/formula/functions/lenb.js +36 -22
- package/dist/formula/functions/lenb.js.map +1 -1
- package/dist/formula/functions/ln.js +38 -24
- package/dist/formula/functions/ln.js.map +1 -1
- package/dist/formula/functions/log.js +43 -29
- package/dist/formula/functions/log.js.map +1 -1
- package/dist/formula/functions/log10.js +38 -24
- package/dist/formula/functions/log10.js.map +1 -1
- package/dist/formula/functions/lt.js +37 -23
- package/dist/formula/functions/lt.js.map +1 -1
- package/dist/formula/functions/lte.js +37 -23
- package/dist/formula/functions/lte.js.map +1 -1
- package/dist/formula/functions/max.js +52 -38
- package/dist/formula/functions/max.js.map +1 -1
- package/dist/formula/functions/min.js +52 -38
- package/dist/formula/functions/min.js.map +1 -1
- package/dist/formula/functions/minus.js +57 -43
- package/dist/formula/functions/minus.js.map +1 -1
- package/dist/formula/functions/mod.js +40 -26
- package/dist/formula/functions/mod.js.map +1 -1
- package/dist/formula/functions/mod.spec.js +58 -46
- package/dist/formula/functions/mod.spec.js.map +1 -1
- package/dist/formula/functions/multiply.js +37 -23
- package/dist/formula/functions/multiply.js.map +1 -1
- package/dist/formula/functions/ne.js +35 -21
- package/dist/formula/functions/ne.js.map +1 -1
- package/dist/formula/functions/not.js +40 -26
- package/dist/formula/functions/not.js.map +1 -1
- package/dist/formula/functions/now.js +31 -17
- package/dist/formula/functions/now.js.map +1 -1
- package/dist/formula/functions/or.js +38 -24
- package/dist/formula/functions/or.js.map +1 -1
- package/dist/formula/functions/pi.js +29 -15
- package/dist/formula/functions/pi.js.map +1 -1
- package/dist/formula/functions/power.js +34 -20
- package/dist/formula/functions/power.js.map +1 -1
- package/dist/formula/functions/product.js +47 -33
- package/dist/formula/functions/product.js.map +1 -1
- package/dist/formula/functions/radians.js +36 -22
- package/dist/formula/functions/radians.js.map +1 -1
- package/dist/formula/functions/rand.js +29 -15
- package/dist/formula/functions/rand.js.map +1 -1
- package/dist/formula/functions/round.js +44 -30
- package/dist/formula/functions/round.js.map +1 -1
- package/dist/formula/functions/rounddown.js +44 -30
- package/dist/formula/functions/rounddown.js.map +1 -1
- package/dist/formula/functions/roundup.js +44 -30
- package/dist/formula/functions/roundup.js.map +1 -1
- package/dist/formula/functions/row.js +38 -24
- package/dist/formula/functions/row.js.map +1 -1
- package/dist/formula/functions/sin.js +36 -22
- package/dist/formula/functions/sin.js.map +1 -1
- package/dist/formula/functions/sqrt.js +38 -24
- package/dist/formula/functions/sqrt.js.map +1 -1
- package/dist/formula/functions/sum.js +52 -38
- package/dist/formula/functions/sum.js.map +1 -1
- package/dist/formula/functions/sum.spec.js +45 -33
- package/dist/formula/functions/sum.spec.js.map +1 -1
- package/dist/formula/functions/sumif.js +66 -52
- package/dist/formula/functions/sumif.js.map +1 -1
- package/dist/formula/functions/tan.js +36 -22
- package/dist/formula/functions/tan.js.map +1 -1
- package/dist/formula/functions/uminus.js +33 -19
- package/dist/formula/functions/uminus.js.map +1 -1
- package/dist/formula/functions/vlookup.js +77 -63
- package/dist/formula/functions/vlookup.js.map +1 -1
- package/dist/formula/mapping.js +126 -113
- package/dist/formula/mapping.js.map +1 -1
- package/dist/formula/solver.js +71 -56
- package/dist/formula/solver.js.map +1 -1
- package/dist/index.js +41 -10
- package/dist/index.js.map +1 -1
- package/dist/lib/autofill.js +344 -330
- package/dist/lib/autofill.js.map +1 -1
- package/dist/lib/clipboard.js +55 -41
- package/dist/lib/clipboard.js.map +1 -1
- package/dist/lib/converters.js +140 -119
- package/dist/lib/converters.js.map +1 -1
- package/dist/lib/structs.js +266 -228
- package/dist/lib/structs.js.map +1 -1
- package/dist/lib/table.js +915 -900
- package/dist/lib/table.js.map +1 -1
- package/dist/lib/time.js +69 -55
- package/dist/lib/time.js.map +1 -1
- package/dist/lib/virtualization.d.ts +10 -1
- package/dist/lib/virtualization.d.ts.map +1 -1
- package/dist/lib/virtualization.js +126 -103
- package/dist/lib/virtualization.js.map +1 -1
- package/dist/parsers/core.js +119 -105
- package/dist/parsers/core.js.map +1 -1
- package/dist/renderers/checkbox.js +24 -8
- package/dist/renderers/checkbox.js.map +1 -1
- package/dist/renderers/core.js +139 -125
- package/dist/renderers/core.js.map +1 -1
- package/dist/renderers/thousand_separator.js +25 -12
- package/dist/renderers/thousand_separator.js.map +1 -1
- package/dist/store/actions.d.ts.map +1 -1
- package/dist/store/actions.js +498 -479
- package/dist/store/actions.js.map +1 -1
- package/dist/store/helpers.js +88 -72
- package/dist/store/helpers.js.map +1 -1
- package/dist/store/index.js +38 -2
- package/dist/store/index.js.map +1 -1
- package/dist/styles/embedder.js +27 -13
- package/dist/styles/embedder.js.map +1 -1
- package/dist/styles/minified.js +16 -3
- package/dist/styles/minified.js.map +1 -1
- package/dist/types.d.ts +4 -4
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +12 -1
- package/dist/utils.js +19 -5
- package/dist/utils.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,541 +1,567 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
if (
|
|
7
|
-
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
export class Unreferenced extends Entity {
|
|
32
|
-
evaluate({}) {
|
|
33
|
-
throw new FormulaError("#REF!", `Reference does not exist.`);
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
export class InvalidRef extends Entity {
|
|
37
|
-
evaluate({}) {
|
|
38
|
-
throw new FormulaError("#NAME?", `Invalid ref: ${this.value}`);
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
export class Ref extends Entity {
|
|
42
|
-
constructor(value) {
|
|
43
|
-
super(value.toUpperCase());
|
|
44
|
-
}
|
|
45
|
-
evaluate({ table }) {
|
|
46
|
-
const { y, x } = a2p(this.value);
|
|
47
|
-
return table.trim({ top: y, left: x, bottom: y, right: x });
|
|
48
|
-
}
|
|
49
|
-
id(table) {
|
|
50
|
-
const id = table.getIdByAddress(this.value);
|
|
51
|
-
if (id) {
|
|
52
|
-
return id;
|
|
1
|
+
(function (factory) {
|
|
2
|
+
if (typeof module === "object" && typeof module.exports === "object") {
|
|
3
|
+
var v = factory(require, exports);
|
|
4
|
+
if (v !== undefined) module.exports = v;
|
|
5
|
+
}
|
|
6
|
+
else if (typeof define === "function" && define.amd) {
|
|
7
|
+
define(["require", "exports", "../lib/structs", "../lib/converters"], factory);
|
|
8
|
+
}
|
|
9
|
+
})(function (require, exports) {
|
|
10
|
+
"use strict";
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.convertFormulaAbsolute = exports.Parser = exports.Lexer = exports.Token = exports.Function = exports.IdRange = exports.Id = exports.Range = exports.Ref = exports.InvalidRef = exports.Unreferenced = exports.Value = exports.FormulaError = void 0;
|
|
13
|
+
const structs_1 = require("../lib/structs");
|
|
14
|
+
const converters_1 = require("../lib/converters");
|
|
15
|
+
// strip sharp and dollars
|
|
16
|
+
const getId = (idString, stripAbsolute = true) => {
|
|
17
|
+
let id = idString.slice(1);
|
|
18
|
+
if (stripAbsolute && id.startsWith("$")) {
|
|
19
|
+
id = id.slice(1);
|
|
20
|
+
}
|
|
21
|
+
if (stripAbsolute && id.endsWith("$")) {
|
|
22
|
+
id = id.slice(0, -1);
|
|
23
|
+
}
|
|
24
|
+
return id;
|
|
25
|
+
};
|
|
26
|
+
class FormulaError {
|
|
27
|
+
constructor(code, message, error) {
|
|
28
|
+
this.code = code;
|
|
29
|
+
this.message = message;
|
|
30
|
+
this.error = error;
|
|
53
31
|
}
|
|
54
|
-
return this.value;
|
|
55
32
|
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
33
|
+
exports.FormulaError = FormulaError;
|
|
34
|
+
class Entity {
|
|
35
|
+
constructor(value) {
|
|
36
|
+
this.value = value;
|
|
37
|
+
}
|
|
60
38
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
39
|
+
class Value extends Entity {
|
|
40
|
+
evaluate({}) {
|
|
41
|
+
return this.value;
|
|
42
|
+
}
|
|
64
43
|
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
44
|
+
exports.Value = Value;
|
|
45
|
+
class Unreferenced extends Entity {
|
|
46
|
+
evaluate({}) {
|
|
47
|
+
throw new FormulaError("#REF!", `Reference does not exist.`);
|
|
48
|
+
}
|
|
70
49
|
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
start += "1";
|
|
50
|
+
exports.Unreferenced = Unreferenced;
|
|
51
|
+
class InvalidRef extends Entity {
|
|
52
|
+
evaluate({}) {
|
|
53
|
+
throw new FormulaError("#NAME?", `Invalid ref: ${this.value}`);
|
|
76
54
|
}
|
|
77
|
-
|
|
78
|
-
|
|
55
|
+
}
|
|
56
|
+
exports.InvalidRef = InvalidRef;
|
|
57
|
+
class Ref extends Entity {
|
|
58
|
+
constructor(value) {
|
|
59
|
+
super(value.toUpperCase());
|
|
79
60
|
}
|
|
80
|
-
|
|
81
|
-
|
|
61
|
+
evaluate({ table }) {
|
|
62
|
+
const { y, x } = (0, converters_1.a2p)(this.value);
|
|
63
|
+
return table.trim({ top: y, left: x, bottom: y, right: x });
|
|
82
64
|
}
|
|
83
|
-
|
|
84
|
-
|
|
65
|
+
id(table) {
|
|
66
|
+
const id = table.getIdByAddress(this.value);
|
|
67
|
+
if (id) {
|
|
68
|
+
return id;
|
|
69
|
+
}
|
|
70
|
+
return this.value;
|
|
85
71
|
}
|
|
86
|
-
return `${start}:${end}`;
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
export class Id extends Entity {
|
|
90
|
-
evaluate({ table }) {
|
|
91
|
-
const id = getId(this.value);
|
|
92
|
-
const { y, x } = table.getPointById(id);
|
|
93
|
-
return table.trim({ top: y, left: x, bottom: y, right: x });
|
|
94
|
-
}
|
|
95
|
-
ref(table, slideY = 0, slideX = 0) {
|
|
96
|
-
return table.getAddressById(getId(this.value, false), slideY, slideX);
|
|
97
72
|
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
73
|
+
exports.Ref = Ref;
|
|
74
|
+
class Range extends Entity {
|
|
75
|
+
constructor(value) {
|
|
76
|
+
super(value.toUpperCase());
|
|
102
77
|
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
.
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
.
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
export class Function {
|
|
127
|
-
constructor(name, precedence = 0, args = []) {
|
|
128
|
-
this.name = name;
|
|
129
|
-
this.precedence = precedence;
|
|
130
|
-
this.args = args;
|
|
131
|
-
}
|
|
132
|
-
evaluate({ table }) {
|
|
133
|
-
const name = this.name.toLowerCase();
|
|
134
|
-
const Func = table.getFunction(name);
|
|
135
|
-
if (Func == null) {
|
|
136
|
-
throw new FormulaError("#NAME?", `Unknown function: ${name}`);
|
|
137
|
-
}
|
|
138
|
-
const func = new Func({ args: this.args, table });
|
|
139
|
-
return func.call();
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
const ZERO = new Value(0);
|
|
143
|
-
const INFIX_FUNCTION_NAME_MAP = {
|
|
144
|
-
"+": "add",
|
|
145
|
-
"-": "minus",
|
|
146
|
-
"/": "divide",
|
|
147
|
-
"*": "multiply",
|
|
148
|
-
"^": "power",
|
|
149
|
-
"&": "concat",
|
|
150
|
-
"=": "eq",
|
|
151
|
-
"<>": "ne",
|
|
152
|
-
">": "gt",
|
|
153
|
-
">=": "gte",
|
|
154
|
-
"<": "lt",
|
|
155
|
-
"<=": "lte",
|
|
156
|
-
};
|
|
157
|
-
const PREFIX_FUNCTION_NAME_MAP = {
|
|
158
|
-
"-": "uminus",
|
|
159
|
-
};
|
|
160
|
-
export class Token {
|
|
161
|
-
constructor(type, entity, precedence = 0) {
|
|
162
|
-
this.type = type;
|
|
163
|
-
this.entity = entity;
|
|
164
|
-
this.precedence = precedence;
|
|
165
|
-
}
|
|
166
|
-
convert() {
|
|
167
|
-
switch (this.type) {
|
|
168
|
-
case "VALUE":
|
|
169
|
-
return new Value(this.entity);
|
|
170
|
-
case "ID":
|
|
171
|
-
return new Id(this.entity);
|
|
172
|
-
case "ID_RANGE":
|
|
173
|
-
return new IdRange(this.entity);
|
|
174
|
-
case "REF":
|
|
175
|
-
return new Ref(this.entity);
|
|
176
|
-
case "RANGE":
|
|
177
|
-
return new Range(this.entity);
|
|
178
|
-
case "INFIX_OPERATOR": {
|
|
179
|
-
const name = INFIX_FUNCTION_NAME_MAP[this.entity];
|
|
180
|
-
return new Function(name, this.precedence);
|
|
78
|
+
evaluate({ table }) {
|
|
79
|
+
const area = (0, structs_1.rangeToArea)(this.complementRange(table));
|
|
80
|
+
return table.trim(area);
|
|
81
|
+
}
|
|
82
|
+
idRange(table) {
|
|
83
|
+
return this.value
|
|
84
|
+
.split(":")
|
|
85
|
+
.map((ref) => table.getIdByAddress(ref))
|
|
86
|
+
.join(":");
|
|
87
|
+
}
|
|
88
|
+
complementRange(table) {
|
|
89
|
+
const cells = this.value.split(":");
|
|
90
|
+
let [start = "", end = ""] = cells;
|
|
91
|
+
if (!start.match(/[1-9]\d*/)) {
|
|
92
|
+
start += "1";
|
|
93
|
+
}
|
|
94
|
+
if (!start.match(/[a-zA-Z]/)) {
|
|
95
|
+
start = "A" + start;
|
|
96
|
+
}
|
|
97
|
+
if (!end.match(/[1-9]\d*/)) {
|
|
98
|
+
end += table.getNumRows();
|
|
181
99
|
}
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
return new Function(name, this.precedence);
|
|
100
|
+
if (!end.match(/[a-zA-Z]/)) {
|
|
101
|
+
end = (0, converters_1.x2c)(table.getNumCols() + 1) + end;
|
|
185
102
|
}
|
|
186
|
-
|
|
187
|
-
return new Function(this.entity);
|
|
188
|
-
case "UNREFERENCED":
|
|
189
|
-
return new Unreferenced(this.entity);
|
|
190
|
-
case "INVALID_REF":
|
|
191
|
-
return new InvalidRef(this.entity);
|
|
103
|
+
return `${start}:${end}`;
|
|
192
104
|
}
|
|
193
105
|
}
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
const
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
this.index += base;
|
|
106
|
+
exports.Range = Range;
|
|
107
|
+
class Id extends Entity {
|
|
108
|
+
evaluate({ table }) {
|
|
109
|
+
const id = getId(this.value);
|
|
110
|
+
const { y, x } = table.getPointById(id);
|
|
111
|
+
return table.trim({ top: y, left: x, bottom: y, right: x });
|
|
112
|
+
}
|
|
113
|
+
ref(table, slideY = 0, slideX = 0) {
|
|
114
|
+
return table.getAddressById(getId(this.value, false), slideY, slideX);
|
|
115
|
+
}
|
|
116
|
+
slide(table, slideY = 0, slideX = 0) {
|
|
117
|
+
const address = this.ref(table, slideY, slideX);
|
|
118
|
+
if (address == null || address.length < 2) {
|
|
119
|
+
return "#REF!";
|
|
120
|
+
}
|
|
121
|
+
return table.getIdByAddress(address);
|
|
122
|
+
}
|
|
212
123
|
}
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
124
|
+
exports.Id = Id;
|
|
125
|
+
class IdRange extends Entity {
|
|
126
|
+
evaluate({ table }) {
|
|
127
|
+
const ids = this.value.split(":");
|
|
128
|
+
const [p1, p2] = ids
|
|
129
|
+
.map((id) => getId(id))
|
|
130
|
+
.map((id) => table.getPointById(id));
|
|
131
|
+
return table.trim({ top: p1.y, left: p1.x, bottom: p2.y, right: p2.x });
|
|
132
|
+
}
|
|
133
|
+
range(table, slideY = 0, slideX = 0) {
|
|
134
|
+
return this.value
|
|
135
|
+
.split(":")
|
|
136
|
+
.map((id) => getId(id, false))
|
|
137
|
+
.map((id) => table.getAddressById(id, slideY, slideX))
|
|
138
|
+
.join(":");
|
|
139
|
+
}
|
|
140
|
+
slide(table, slideY = 0, slideX = 0) {
|
|
141
|
+
const range = this.range(table, slideY, slideX);
|
|
142
|
+
return new Range(range).idRange(table);
|
|
143
|
+
}
|
|
216
144
|
}
|
|
217
|
-
|
|
218
|
-
|
|
145
|
+
exports.IdRange = IdRange;
|
|
146
|
+
class Function {
|
|
147
|
+
constructor(name, precedence = 0, args = []) {
|
|
148
|
+
this.name = name;
|
|
149
|
+
this.precedence = precedence;
|
|
150
|
+
this.args = args;
|
|
151
|
+
}
|
|
152
|
+
evaluate({ table }) {
|
|
153
|
+
const name = this.name.toLowerCase();
|
|
154
|
+
const Func = table.getFunction(name);
|
|
155
|
+
if (Func == null) {
|
|
156
|
+
throw new FormulaError("#NAME?", `Unknown function: ${name}`);
|
|
157
|
+
}
|
|
158
|
+
const func = new Func({ args: this.args, table });
|
|
159
|
+
return func.call();
|
|
160
|
+
}
|
|
219
161
|
}
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
162
|
+
exports.Function = Function;
|
|
163
|
+
const ZERO = new Value(0);
|
|
164
|
+
const INFIX_FUNCTION_NAME_MAP = {
|
|
165
|
+
"+": "add",
|
|
166
|
+
"-": "minus",
|
|
167
|
+
"/": "divide",
|
|
168
|
+
"*": "multiply",
|
|
169
|
+
"^": "power",
|
|
170
|
+
"&": "concat",
|
|
171
|
+
"=": "eq",
|
|
172
|
+
"<>": "ne",
|
|
173
|
+
">": "gt",
|
|
174
|
+
">=": "gte",
|
|
175
|
+
"<": "lt",
|
|
176
|
+
"<=": "lte",
|
|
177
|
+
};
|
|
178
|
+
const PREFIX_FUNCTION_NAME_MAP = {
|
|
179
|
+
"-": "uminus",
|
|
180
|
+
};
|
|
181
|
+
class Token {
|
|
182
|
+
constructor(type, entity, precedence = 0) {
|
|
183
|
+
this.type = type;
|
|
184
|
+
this.entity = entity;
|
|
185
|
+
this.precedence = precedence;
|
|
186
|
+
}
|
|
187
|
+
convert() {
|
|
188
|
+
switch (this.type) {
|
|
224
189
|
case "VALUE":
|
|
225
|
-
|
|
226
|
-
return t.entity;
|
|
227
|
-
}
|
|
228
|
-
return `"${t.entity}"`;
|
|
190
|
+
return new Value(this.entity);
|
|
229
191
|
case "ID":
|
|
230
|
-
return new Id(
|
|
192
|
+
return new Id(this.entity);
|
|
231
193
|
case "ID_RANGE":
|
|
232
|
-
return new IdRange(
|
|
194
|
+
return new IdRange(this.entity);
|
|
233
195
|
case "REF":
|
|
234
|
-
return new Ref(
|
|
196
|
+
return new Ref(this.entity);
|
|
235
197
|
case "RANGE":
|
|
236
|
-
return new Range(
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
return
|
|
251
|
-
case "ID":
|
|
252
|
-
return new Id(t.entity).ref(table);
|
|
253
|
-
case "ID_RANGE":
|
|
254
|
-
return new IdRange(t.entity).range(table);
|
|
198
|
+
return new Range(this.entity);
|
|
199
|
+
case "INFIX_OPERATOR": {
|
|
200
|
+
const name = INFIX_FUNCTION_NAME_MAP[this.entity];
|
|
201
|
+
return new Function(name, this.precedence);
|
|
202
|
+
}
|
|
203
|
+
case "PREFIX_OPERATOR": {
|
|
204
|
+
const name = PREFIX_FUNCTION_NAME_MAP[this.entity];
|
|
205
|
+
return new Function(name, this.precedence);
|
|
206
|
+
}
|
|
207
|
+
case "FUNCTION":
|
|
208
|
+
return new Function(this.entity);
|
|
209
|
+
case "UNREFERENCED":
|
|
210
|
+
return new Unreferenced(this.entity);
|
|
211
|
+
case "INVALID_REF":
|
|
212
|
+
return new InvalidRef(this.entity);
|
|
255
213
|
}
|
|
256
|
-
|
|
257
|
-
})
|
|
258
|
-
.join("");
|
|
214
|
+
}
|
|
259
215
|
}
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
216
|
+
exports.Token = Token;
|
|
217
|
+
const isWhiteSpace = (char) => {
|
|
218
|
+
return char === " " || char === "\n" || char === "\t";
|
|
219
|
+
};
|
|
220
|
+
const TOKEN_OPEN = new Token("OPEN", "("), TOKEN_CLOSE = new Token("CLOSE", ")"), TOKEN_COMMA = new Token("COMMA", ","), TOKEN_ADD = new Token("INFIX_OPERATOR", "+", 3), TOKEN_MINUS = new Token("INFIX_OPERATOR", "-", 3), TOKEN_UMINUS = new Token("PREFIX_OPERATOR", "-", 6), TOKEN_DIVIDE = new Token("INFIX_OPERATOR", "/", 4), TOKEN_MULTIPLY = new Token("INFIX_OPERATOR", "*", 4), TOKEN_POWER = new Token("INFIX_OPERATOR", "^", 5), TOKEN_CONCAT = new Token("INFIX_OPERATOR", "&", 4), TOKEN_GTE = new Token("INFIX_OPERATOR", ">=", 2), TOKEN_GT = new Token("INFIX_OPERATOR", ">", 2), TOKEN_LTE = new Token("INFIX_OPERATOR", "<=", 2), TOKEN_LT = new Token("INFIX_OPERATOR", "<", 2), TOKEN_NE = new Token("INFIX_OPERATOR", "<>", 1), TOKEN_EQ = new Token("INFIX_OPERATOR", "=", 1);
|
|
221
|
+
const BOOLS = { ["true"]: true, ["false"]: false };
|
|
222
|
+
class Lexer {
|
|
223
|
+
constructor(formula) {
|
|
224
|
+
this.tokens = [];
|
|
225
|
+
this.formula = formula;
|
|
226
|
+
this.index = 0;
|
|
227
|
+
this.tokens = [];
|
|
228
|
+
}
|
|
229
|
+
isWhiteSpace() {
|
|
230
|
+
return isWhiteSpace(this.formula[this.index]);
|
|
231
|
+
}
|
|
232
|
+
next(base = 1) {
|
|
233
|
+
this.index += base;
|
|
234
|
+
}
|
|
235
|
+
get(base = 0) {
|
|
236
|
+
const c = this.formula[this.index + base];
|
|
237
|
+
return c;
|
|
238
|
+
}
|
|
239
|
+
getToken(base = 0) {
|
|
240
|
+
return this.tokens[this.tokens.length + base];
|
|
241
|
+
}
|
|
242
|
+
stringifyToId(table, slideY = 0, slideX = 0) {
|
|
243
|
+
return this.tokens
|
|
244
|
+
.map((t) => {
|
|
245
|
+
switch (t.type) {
|
|
246
|
+
case "VALUE":
|
|
247
|
+
if (typeof t.entity === "number" || typeof t.entity === "boolean") {
|
|
248
|
+
return t.entity;
|
|
249
|
+
}
|
|
250
|
+
return `"${t.entity}"`;
|
|
251
|
+
case "ID":
|
|
252
|
+
return new Id(t.entity).slide(table, slideY, slideX);
|
|
253
|
+
case "ID_RANGE":
|
|
254
|
+
return new IdRange(t.entity).slide(table, slideY, slideX);
|
|
255
|
+
case "REF":
|
|
256
|
+
return new Ref(t.entity).id(table);
|
|
257
|
+
case "RANGE":
|
|
258
|
+
return new Range(t.entity).idRange(table);
|
|
292
259
|
}
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
260
|
+
return t.entity;
|
|
261
|
+
})
|
|
262
|
+
.join("");
|
|
263
|
+
}
|
|
264
|
+
stringifyToRef(table) {
|
|
265
|
+
return this.tokens
|
|
266
|
+
.map((t) => {
|
|
267
|
+
switch (t.type) {
|
|
268
|
+
case "VALUE":
|
|
269
|
+
if (typeof t.entity === "number" || typeof t.entity === "boolean") {
|
|
270
|
+
return t.entity;
|
|
271
|
+
}
|
|
272
|
+
return `"${t.entity}"`;
|
|
273
|
+
case "ID":
|
|
274
|
+
return new Id(t.entity).ref(table);
|
|
275
|
+
case "ID_RANGE":
|
|
276
|
+
return new IdRange(t.entity).range(table);
|
|
277
|
+
}
|
|
278
|
+
return t.entity;
|
|
279
|
+
})
|
|
280
|
+
.join("");
|
|
281
|
+
}
|
|
282
|
+
tokenize() {
|
|
283
|
+
var _a, _b;
|
|
284
|
+
while (this.index <= this.formula.length) {
|
|
285
|
+
this.skipSpaces();
|
|
286
|
+
const char = this.get();
|
|
287
|
+
this.next();
|
|
288
|
+
switch (char) {
|
|
289
|
+
case undefined:
|
|
290
|
+
return;
|
|
291
|
+
case "(":
|
|
292
|
+
this.tokens.push(TOKEN_OPEN);
|
|
312
293
|
continue;
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
294
|
+
case ")":
|
|
295
|
+
this.tokens.push(TOKEN_CLOSE);
|
|
296
|
+
continue;
|
|
297
|
+
case ",":
|
|
298
|
+
this.tokens.push(TOKEN_COMMA);
|
|
299
|
+
continue;
|
|
300
|
+
case "+":
|
|
301
|
+
this.tokens.push(TOKEN_ADD);
|
|
302
|
+
continue;
|
|
303
|
+
case "-": {
|
|
304
|
+
const prev1 = (_a = this.getToken(-1)) === null || _a === void 0 ? void 0 : _a.type;
|
|
305
|
+
const prev2 = (_b = this.getToken(-2)) === null || _b === void 0 ? void 0 : _b.type;
|
|
306
|
+
if (prev1 === "INFIX_OPERATOR" ||
|
|
307
|
+
(prev1 === "SPACE" && prev2 === "INFIX_OPERATOR")) {
|
|
308
|
+
this.tokens.push(TOKEN_UMINUS);
|
|
309
|
+
}
|
|
310
|
+
else {
|
|
311
|
+
this.tokens.push(TOKEN_MINUS);
|
|
312
|
+
}
|
|
320
313
|
continue;
|
|
321
314
|
}
|
|
322
|
-
|
|
323
|
-
this.
|
|
324
|
-
|
|
315
|
+
case "/":
|
|
316
|
+
this.tokens.push(TOKEN_DIVIDE);
|
|
317
|
+
continue;
|
|
318
|
+
case "*":
|
|
319
|
+
this.tokens.push(TOKEN_MULTIPLY);
|
|
320
|
+
continue;
|
|
321
|
+
case "^":
|
|
322
|
+
this.tokens.push(TOKEN_POWER);
|
|
323
|
+
continue;
|
|
324
|
+
case "&":
|
|
325
|
+
this.tokens.push(TOKEN_CONCAT);
|
|
326
|
+
continue;
|
|
327
|
+
case "=":
|
|
328
|
+
this.tokens.push(TOKEN_EQ);
|
|
329
|
+
continue;
|
|
330
|
+
case ">":
|
|
331
|
+
if (this.get() === "=") {
|
|
332
|
+
this.next();
|
|
333
|
+
this.tokens.push(TOKEN_GTE);
|
|
334
|
+
continue;
|
|
335
|
+
}
|
|
336
|
+
this.tokens.push(TOKEN_GT);
|
|
337
|
+
continue;
|
|
338
|
+
case "<":
|
|
339
|
+
if (this.get() === "=") {
|
|
340
|
+
this.next();
|
|
341
|
+
this.tokens.push(TOKEN_LTE);
|
|
342
|
+
continue;
|
|
343
|
+
}
|
|
344
|
+
if (this.get() === ">") {
|
|
345
|
+
this.next();
|
|
346
|
+
this.tokens.push(TOKEN_NE);
|
|
347
|
+
continue;
|
|
348
|
+
}
|
|
349
|
+
this.tokens.push(TOKEN_LT);
|
|
350
|
+
continue;
|
|
351
|
+
case '"': {
|
|
352
|
+
const buf = this.getString();
|
|
353
|
+
this.tokens.push(new Token("VALUE", buf));
|
|
325
354
|
continue;
|
|
326
355
|
}
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
const
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
} // switch end
|
|
335
|
-
let buf = char;
|
|
336
|
-
while (true) {
|
|
337
|
-
const c = this.get();
|
|
338
|
-
if (c === "(") {
|
|
339
|
-
this.tokens.push(new Token("FUNCTION", buf), TOKEN_OPEN);
|
|
340
|
-
this.next();
|
|
341
|
-
break;
|
|
342
|
-
}
|
|
343
|
-
if (c == null || c.match(/[ +\-/*^&=<>),]/)) {
|
|
344
|
-
if (buf.length === 0) {
|
|
356
|
+
} // switch end
|
|
357
|
+
let buf = char;
|
|
358
|
+
while (true) {
|
|
359
|
+
const c = this.get();
|
|
360
|
+
if (c === "(") {
|
|
361
|
+
this.tokens.push(new Token("FUNCTION", buf), TOKEN_OPEN);
|
|
362
|
+
this.next();
|
|
345
363
|
break;
|
|
346
364
|
}
|
|
347
|
-
if (
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
else {
|
|
351
|
-
// @ts-ignore
|
|
352
|
-
const bool = BOOLS[buf.toLowerCase()];
|
|
353
|
-
if (bool != null) {
|
|
354
|
-
this.tokens.push(new Token("VALUE", bool));
|
|
355
|
-
}
|
|
356
|
-
else if (buf.startsWith("#")) {
|
|
357
|
-
if (buf === "#REF!") {
|
|
358
|
-
this.tokens.push(new Token("UNREFERENCED", buf));
|
|
359
|
-
}
|
|
360
|
-
else if (buf.indexOf(":") !== -1) {
|
|
361
|
-
this.tokens.push(new Token("ID_RANGE", buf));
|
|
362
|
-
}
|
|
363
|
-
else {
|
|
364
|
-
this.tokens.push(new Token("ID", buf));
|
|
365
|
-
}
|
|
365
|
+
if (c == null || c.match(/[ +\-/*^&=<>),]/)) {
|
|
366
|
+
if (buf.length === 0) {
|
|
367
|
+
break;
|
|
366
368
|
}
|
|
367
|
-
|
|
368
|
-
this.tokens.push(new Token("
|
|
369
|
+
if (buf.match(/^[+-]?(\d*[.])?\d+$/)) {
|
|
370
|
+
this.tokens.push(new Token("VALUE", parseFloat(buf)));
|
|
369
371
|
}
|
|
370
372
|
else {
|
|
371
373
|
// @ts-ignore
|
|
372
|
-
|
|
373
|
-
|
|
374
|
+
const bool = BOOLS[buf.toLowerCase()];
|
|
375
|
+
if (bool != null) {
|
|
376
|
+
this.tokens.push(new Token("VALUE", bool));
|
|
377
|
+
}
|
|
378
|
+
else if (buf.startsWith("#")) {
|
|
379
|
+
if (buf === "#REF!") {
|
|
380
|
+
this.tokens.push(new Token("UNREFERENCED", buf));
|
|
381
|
+
}
|
|
382
|
+
else if (buf.indexOf(":") !== -1) {
|
|
383
|
+
this.tokens.push(new Token("ID_RANGE", buf));
|
|
384
|
+
}
|
|
385
|
+
else {
|
|
386
|
+
this.tokens.push(new Token("ID", buf));
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
else if (buf.indexOf(":") !== -1) {
|
|
390
|
+
this.tokens.push(new Token("RANGE", buf));
|
|
374
391
|
}
|
|
375
392
|
else {
|
|
376
|
-
|
|
393
|
+
// @ts-ignore
|
|
394
|
+
if (isNaN(buf[buf.length - 1])) {
|
|
395
|
+
this.tokens.push(new Token("INVALID_REF", buf));
|
|
396
|
+
}
|
|
397
|
+
else {
|
|
398
|
+
this.tokens.push(new Token("REF", buf));
|
|
399
|
+
}
|
|
377
400
|
}
|
|
378
401
|
}
|
|
402
|
+
break;
|
|
379
403
|
}
|
|
380
|
-
|
|
381
|
-
}
|
|
382
|
-
buf += c;
|
|
383
|
-
this.next();
|
|
384
|
-
}
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
|
-
skipSpaces() {
|
|
388
|
-
let space = "";
|
|
389
|
-
while (this.isWhiteSpace()) {
|
|
390
|
-
space += this.formula[this.index++];
|
|
391
|
-
}
|
|
392
|
-
if (space !== "") {
|
|
393
|
-
this.tokens.push(new Token("SPACE", space));
|
|
394
|
-
}
|
|
395
|
-
}
|
|
396
|
-
getString() {
|
|
397
|
-
let buf = "";
|
|
398
|
-
while (true) {
|
|
399
|
-
const c = this.get();
|
|
400
|
-
this.next();
|
|
401
|
-
if (c == null) {
|
|
402
|
-
break;
|
|
403
|
-
}
|
|
404
|
-
if (c === '"') {
|
|
405
|
-
if (this.get() === '"') {
|
|
406
|
-
// escape
|
|
407
|
-
buf += '"';
|
|
404
|
+
buf += c;
|
|
408
405
|
this.next();
|
|
409
|
-
continue;
|
|
410
|
-
}
|
|
411
|
-
else {
|
|
412
|
-
break;
|
|
413
406
|
}
|
|
414
407
|
}
|
|
415
|
-
else {
|
|
416
|
-
buf += c;
|
|
417
|
-
}
|
|
418
408
|
}
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
constructor(tokens) {
|
|
424
|
-
this.index = 0;
|
|
425
|
-
this.depth = 0;
|
|
426
|
-
this.tokens = tokens;
|
|
427
|
-
}
|
|
428
|
-
build() {
|
|
429
|
-
const { expr } = this.parse(false);
|
|
430
|
-
return expr;
|
|
431
|
-
}
|
|
432
|
-
parse(underFunction) {
|
|
433
|
-
const stack = [];
|
|
434
|
-
let lastOperator;
|
|
435
|
-
const complement = (hasNext = false) => {
|
|
436
|
-
if (lastOperator) {
|
|
437
|
-
const outer = stack.pop();
|
|
438
|
-
lastOperator.args.push(outer);
|
|
409
|
+
skipSpaces() {
|
|
410
|
+
let space = "";
|
|
411
|
+
while (this.isWhiteSpace()) {
|
|
412
|
+
space += this.formula[this.index++];
|
|
439
413
|
}
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
while (this.tokens.length > this.index) {
|
|
443
|
-
const token = this.tokens[this.index++];
|
|
444
|
-
if (token.type === "SPACE") {
|
|
445
|
-
continue;
|
|
414
|
+
if (space !== "") {
|
|
415
|
+
this.tokens.push(new Token("SPACE", space));
|
|
446
416
|
}
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
417
|
+
}
|
|
418
|
+
getString() {
|
|
419
|
+
let buf = "";
|
|
420
|
+
while (true) {
|
|
421
|
+
const c = this.get();
|
|
422
|
+
this.next();
|
|
423
|
+
if (c == null) {
|
|
424
|
+
break;
|
|
450
425
|
}
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
token.type === "RANGE" ||
|
|
458
|
-
token.type === "UNREFERENCED" ||
|
|
459
|
-
token.type === "INVALID_REF") {
|
|
460
|
-
const expr = token.convert();
|
|
461
|
-
stack.push(expr);
|
|
462
|
-
}
|
|
463
|
-
else if (token.type === "FUNCTION") {
|
|
464
|
-
this.index++;
|
|
465
|
-
this.depth++;
|
|
466
|
-
const func = token.convert();
|
|
467
|
-
stack.push(func);
|
|
468
|
-
while (true) {
|
|
469
|
-
const { expr, hasNext } = this.parse(true);
|
|
470
|
-
if (expr) {
|
|
471
|
-
func.args.push(expr);
|
|
426
|
+
if (c === '"') {
|
|
427
|
+
if (this.get() === '"') {
|
|
428
|
+
// escape
|
|
429
|
+
buf += '"';
|
|
430
|
+
this.next();
|
|
431
|
+
continue;
|
|
472
432
|
}
|
|
473
|
-
|
|
433
|
+
else {
|
|
474
434
|
break;
|
|
475
435
|
}
|
|
476
436
|
}
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
this.depth++;
|
|
480
|
-
const { expr } = this.parse(false);
|
|
481
|
-
stack.push(expr);
|
|
482
|
-
}
|
|
483
|
-
else if (token.type === "CLOSE") {
|
|
484
|
-
if (this.depth-- === 0) {
|
|
485
|
-
throw new FormulaError("#ERROR!", "Unexpected end paren");
|
|
437
|
+
else {
|
|
438
|
+
buf += c;
|
|
486
439
|
}
|
|
487
|
-
return complement();
|
|
488
440
|
}
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
441
|
+
return buf;
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
exports.Lexer = Lexer;
|
|
445
|
+
class Parser {
|
|
446
|
+
constructor(tokens) {
|
|
447
|
+
this.index = 0;
|
|
448
|
+
this.depth = 0;
|
|
449
|
+
this.tokens = tokens;
|
|
450
|
+
}
|
|
451
|
+
build() {
|
|
452
|
+
const { expr } = this.parse(false);
|
|
453
|
+
return expr;
|
|
454
|
+
}
|
|
455
|
+
parse(underFunction) {
|
|
456
|
+
const stack = [];
|
|
457
|
+
let lastOperator;
|
|
458
|
+
const complement = (hasNext = false) => {
|
|
459
|
+
if (lastOperator) {
|
|
460
|
+
const outer = stack.pop();
|
|
461
|
+
lastOperator.args.push(outer);
|
|
462
|
+
}
|
|
463
|
+
return { hasNext, expr: stack.shift() };
|
|
464
|
+
};
|
|
465
|
+
while (this.tokens.length > this.index) {
|
|
466
|
+
const token = this.tokens[this.index++];
|
|
467
|
+
if (token.type === "SPACE") {
|
|
468
|
+
continue;
|
|
469
|
+
}
|
|
470
|
+
if (token.type === "COMMA") {
|
|
471
|
+
if (!underFunction) {
|
|
472
|
+
throw new FormulaError("#ERROR!", "Invalid comma");
|
|
498
473
|
}
|
|
474
|
+
return complement(true);
|
|
499
475
|
}
|
|
500
|
-
if (
|
|
501
|
-
|
|
502
|
-
|
|
476
|
+
else if (token.type === "VALUE" ||
|
|
477
|
+
token.type === "ID" ||
|
|
478
|
+
token.type === "ID_RANGE" ||
|
|
479
|
+
token.type === "REF" ||
|
|
480
|
+
token.type === "RANGE" ||
|
|
481
|
+
token.type === "UNREFERENCED" ||
|
|
482
|
+
token.type === "INVALID_REF") {
|
|
483
|
+
const expr = token.convert();
|
|
484
|
+
stack.push(expr);
|
|
503
485
|
}
|
|
504
|
-
else if (
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
486
|
+
else if (token.type === "FUNCTION") {
|
|
487
|
+
this.index++;
|
|
488
|
+
this.depth++;
|
|
489
|
+
const func = token.convert();
|
|
490
|
+
stack.push(func);
|
|
491
|
+
while (true) {
|
|
492
|
+
const { expr, hasNext } = this.parse(true);
|
|
493
|
+
if (expr) {
|
|
494
|
+
func.args.push(expr);
|
|
495
|
+
}
|
|
496
|
+
if (!hasNext) {
|
|
497
|
+
break;
|
|
498
|
+
}
|
|
499
|
+
}
|
|
508
500
|
}
|
|
509
|
-
else {
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
stack.unshift(operator);
|
|
501
|
+
else if (token.type === "OPEN") {
|
|
502
|
+
this.depth++;
|
|
503
|
+
const { expr } = this.parse(false);
|
|
504
|
+
stack.push(expr);
|
|
514
505
|
}
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
lastOperator.args.push(operator);
|
|
506
|
+
else if (token.type === "CLOSE") {
|
|
507
|
+
if (this.depth-- === 0) {
|
|
508
|
+
throw new FormulaError("#ERROR!", "Unexpected end paren");
|
|
509
|
+
}
|
|
510
|
+
return complement();
|
|
521
511
|
}
|
|
522
|
-
else {
|
|
523
|
-
|
|
512
|
+
else if (token.type === "INFIX_OPERATOR") {
|
|
513
|
+
const operator = token.convert();
|
|
514
|
+
let left = stack.pop();
|
|
515
|
+
if (left == null) {
|
|
516
|
+
if (operator.name === "minus" || operator.name === "add") {
|
|
517
|
+
left = ZERO;
|
|
518
|
+
}
|
|
519
|
+
else {
|
|
520
|
+
throw new FormulaError("#ERROR!", "Missing left expression");
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
if (lastOperator == null) {
|
|
524
|
+
operator.args.push(left);
|
|
525
|
+
stack.unshift(operator);
|
|
526
|
+
}
|
|
527
|
+
else if (operator.precedence > lastOperator.precedence) {
|
|
528
|
+
operator.args.push(left);
|
|
529
|
+
lastOperator.args.push(operator);
|
|
530
|
+
stack.unshift(lastOperator);
|
|
531
|
+
}
|
|
532
|
+
else {
|
|
533
|
+
const outer = stack.shift();
|
|
534
|
+
operator.args.push(outer);
|
|
535
|
+
lastOperator.args.push(left);
|
|
536
|
+
stack.unshift(operator);
|
|
537
|
+
}
|
|
538
|
+
lastOperator = operator;
|
|
539
|
+
}
|
|
540
|
+
else if (token.type === "PREFIX_OPERATOR") {
|
|
541
|
+
const operator = token.convert();
|
|
542
|
+
if (lastOperator) {
|
|
543
|
+
lastOperator.args.push(operator);
|
|
544
|
+
}
|
|
545
|
+
else {
|
|
546
|
+
stack.unshift(operator);
|
|
547
|
+
}
|
|
548
|
+
lastOperator = operator;
|
|
524
549
|
}
|
|
525
|
-
lastOperator = operator;
|
|
526
550
|
}
|
|
551
|
+
return complement();
|
|
527
552
|
}
|
|
528
|
-
return complement();
|
|
529
553
|
}
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
554
|
+
exports.Parser = Parser;
|
|
555
|
+
const convertFormulaAbsolute = ({ value, table, slideY = 0, slideX = 0, }) => {
|
|
556
|
+
if (typeof value === "string" || value instanceof String) {
|
|
557
|
+
if (value.charAt(0) === "=") {
|
|
558
|
+
const lexer = new Lexer(value.substring(1));
|
|
559
|
+
lexer.tokenize();
|
|
560
|
+
return "=" + lexer.stringifyToId(table, slideY, slideX);
|
|
561
|
+
}
|
|
537
562
|
}
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
563
|
+
return value;
|
|
564
|
+
};
|
|
565
|
+
exports.convertFormulaAbsolute = convertFormulaAbsolute;
|
|
566
|
+
});
|
|
541
567
|
//# sourceMappingURL=evaluator.js.map
|