@trebco/treb 23.6.5 → 25.0.0-rc1

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 (217) hide show
  1. package/.eslintignore +8 -0
  2. package/.eslintrc.js +164 -0
  3. package/README-shadow-DOM.md +88 -0
  4. package/README.md +37 -130
  5. package/api-config.json +29 -0
  6. package/api-generator/api-generator-types.ts +82 -0
  7. package/api-generator/api-generator.ts +1172 -0
  8. package/api-generator/package.json +3 -0
  9. package/build/treb-spreadsheet.mjs +14 -0
  10. package/{treb.d.ts → build/treb.d.ts} +285 -269
  11. package/esbuild-custom-element.mjs +336 -0
  12. package/esbuild.js +305 -0
  13. package/package.json +43 -14
  14. package/treb-base-types/package.json +5 -0
  15. package/treb-base-types/src/api_types.ts +36 -0
  16. package/treb-base-types/src/area.ts +583 -0
  17. package/treb-base-types/src/basic_types.ts +45 -0
  18. package/treb-base-types/src/cell.ts +612 -0
  19. package/treb-base-types/src/cells.ts +1066 -0
  20. package/treb-base-types/src/color.ts +124 -0
  21. package/treb-base-types/src/import.ts +71 -0
  22. package/treb-base-types/src/index-standalone.ts +29 -0
  23. package/treb-base-types/src/index.ts +42 -0
  24. package/treb-base-types/src/layout.ts +47 -0
  25. package/treb-base-types/src/localization.ts +187 -0
  26. package/treb-base-types/src/rectangle.ts +145 -0
  27. package/treb-base-types/src/render_text.ts +72 -0
  28. package/treb-base-types/src/style.ts +545 -0
  29. package/treb-base-types/src/table.ts +109 -0
  30. package/treb-base-types/src/text_part.ts +54 -0
  31. package/treb-base-types/src/theme.ts +608 -0
  32. package/treb-base-types/src/union.ts +152 -0
  33. package/treb-base-types/src/value-type.ts +164 -0
  34. package/treb-base-types/style/resizable.css +59 -0
  35. package/treb-calculator/modern.tsconfig.json +11 -0
  36. package/treb-calculator/package.json +5 -0
  37. package/treb-calculator/src/calculator.ts +2546 -0
  38. package/treb-calculator/src/complex-math.ts +558 -0
  39. package/treb-calculator/src/dag/array-vertex.ts +198 -0
  40. package/treb-calculator/src/dag/graph.ts +951 -0
  41. package/treb-calculator/src/dag/leaf_vertex.ts +118 -0
  42. package/treb-calculator/src/dag/spreadsheet_vertex.ts +327 -0
  43. package/treb-calculator/src/dag/spreadsheet_vertex_base.ts +44 -0
  44. package/treb-calculator/src/dag/vertex.ts +352 -0
  45. package/treb-calculator/src/descriptors.ts +162 -0
  46. package/treb-calculator/src/expression-calculator.ts +1069 -0
  47. package/treb-calculator/src/function-error.ts +103 -0
  48. package/treb-calculator/src/function-library.ts +103 -0
  49. package/treb-calculator/src/functions/base-functions.ts +1214 -0
  50. package/treb-calculator/src/functions/checkbox.ts +164 -0
  51. package/treb-calculator/src/functions/complex-functions.ts +253 -0
  52. package/treb-calculator/src/functions/finance-functions.ts +399 -0
  53. package/treb-calculator/src/functions/information-functions.ts +102 -0
  54. package/treb-calculator/src/functions/matrix-functions.ts +182 -0
  55. package/treb-calculator/src/functions/sparkline.ts +335 -0
  56. package/treb-calculator/src/functions/statistics-functions.ts +350 -0
  57. package/treb-calculator/src/functions/text-functions.ts +298 -0
  58. package/treb-calculator/src/index.ts +27 -0
  59. package/treb-calculator/src/notifier-types.ts +59 -0
  60. package/treb-calculator/src/primitives.ts +428 -0
  61. package/treb-calculator/src/utilities.ts +305 -0
  62. package/treb-charts/package.json +5 -0
  63. package/treb-charts/src/chart-functions.ts +156 -0
  64. package/treb-charts/src/chart-types.ts +230 -0
  65. package/treb-charts/src/chart.ts +1288 -0
  66. package/treb-charts/src/index.ts +24 -0
  67. package/treb-charts/src/main.ts +37 -0
  68. package/treb-charts/src/rectangle.ts +52 -0
  69. package/treb-charts/src/renderer.ts +1841 -0
  70. package/treb-charts/src/util.ts +122 -0
  71. package/treb-charts/style/charts.scss +221 -0
  72. package/treb-charts/style/old-charts.scss +250 -0
  73. package/treb-embed/markup/layout.html +137 -0
  74. package/treb-embed/markup/toolbar.html +175 -0
  75. package/treb-embed/modern.tsconfig.json +25 -0
  76. package/treb-embed/src/custom-element/content-types.d.ts +18 -0
  77. package/treb-embed/src/custom-element/global.d.ts +11 -0
  78. package/treb-embed/src/custom-element/spreadsheet-constructor.ts +1227 -0
  79. package/treb-embed/src/custom-element/treb-global.ts +44 -0
  80. package/treb-embed/src/custom-element/treb-spreadsheet-element.ts +52 -0
  81. package/treb-embed/src/embedded-spreadsheet.ts +5362 -0
  82. package/treb-embed/src/index.ts +16 -0
  83. package/treb-embed/src/language-model.ts +41 -0
  84. package/treb-embed/src/options.ts +320 -0
  85. package/treb-embed/src/progress-dialog.ts +228 -0
  86. package/treb-embed/src/selection-state.ts +16 -0
  87. package/treb-embed/src/spinner.ts +42 -0
  88. package/treb-embed/src/toolbar-message.ts +96 -0
  89. package/treb-embed/src/types.ts +167 -0
  90. package/treb-embed/style/autocomplete.scss +103 -0
  91. package/treb-embed/style/dark-theme.scss +114 -0
  92. package/treb-embed/style/defaults.scss +36 -0
  93. package/treb-embed/style/dialog.scss +181 -0
  94. package/treb-embed/style/dropdown-select.scss +101 -0
  95. package/treb-embed/style/formula-bar.scss +193 -0
  96. package/treb-embed/style/grid.scss +374 -0
  97. package/treb-embed/style/layout.scss +424 -0
  98. package/treb-embed/style/mouse-mask.scss +67 -0
  99. package/treb-embed/style/note.scss +92 -0
  100. package/treb-embed/style/overlay-editor.scss +102 -0
  101. package/treb-embed/style/spinner.scss +92 -0
  102. package/treb-embed/style/tab-bar.scss +228 -0
  103. package/treb-embed/style/table.scss +80 -0
  104. package/treb-embed/style/theme-defaults.scss +444 -0
  105. package/treb-embed/style/toolbar.scss +416 -0
  106. package/treb-embed/style/tooltip.scss +68 -0
  107. package/treb-embed/style/treb-icons.scss +130 -0
  108. package/treb-embed/style/treb-spreadsheet-element.scss +20 -0
  109. package/treb-embed/style/z-index.scss +43 -0
  110. package/treb-export/docs/charts.md +68 -0
  111. package/treb-export/modern.tsconfig.json +19 -0
  112. package/treb-export/package.json +4 -0
  113. package/treb-export/src/address-type.ts +77 -0
  114. package/treb-export/src/base-template.ts +22 -0
  115. package/treb-export/src/column-width.ts +85 -0
  116. package/treb-export/src/drawing2/chart-template-components2.ts +389 -0
  117. package/treb-export/src/drawing2/chart2.ts +282 -0
  118. package/treb-export/src/drawing2/column-chart-template2.ts +521 -0
  119. package/treb-export/src/drawing2/donut-chart-template2.ts +296 -0
  120. package/treb-export/src/drawing2/drawing2.ts +355 -0
  121. package/treb-export/src/drawing2/embedded-image.ts +71 -0
  122. package/treb-export/src/drawing2/scatter-chart-template2.ts +555 -0
  123. package/treb-export/src/export-worker/export-worker.ts +99 -0
  124. package/treb-export/src/export-worker/index-modern.ts +22 -0
  125. package/treb-export/src/export2.ts +2204 -0
  126. package/treb-export/src/import2.ts +882 -0
  127. package/treb-export/src/relationship.ts +36 -0
  128. package/treb-export/src/shared-strings2.ts +128 -0
  129. package/treb-export/src/template-2.ts +22 -0
  130. package/treb-export/src/unescape_xml.ts +47 -0
  131. package/treb-export/src/workbook-sheet2.ts +182 -0
  132. package/treb-export/src/workbook-style2.ts +1285 -0
  133. package/treb-export/src/workbook-theme2.ts +88 -0
  134. package/treb-export/src/workbook2.ts +491 -0
  135. package/treb-export/src/xml-utils.ts +201 -0
  136. package/treb-export/template/base/[Content_Types].xml +2 -0
  137. package/treb-export/template/base/_rels/.rels +2 -0
  138. package/treb-export/template/base/docProps/app.xml +2 -0
  139. package/treb-export/template/base/docProps/core.xml +12 -0
  140. package/treb-export/template/base/xl/_rels/workbook.xml.rels +2 -0
  141. package/treb-export/template/base/xl/sharedStrings.xml +2 -0
  142. package/treb-export/template/base/xl/styles.xml +2 -0
  143. package/treb-export/template/base/xl/theme/theme1.xml +2 -0
  144. package/treb-export/template/base/xl/workbook.xml +2 -0
  145. package/treb-export/template/base/xl/worksheets/sheet1.xml +2 -0
  146. package/treb-export/template/base.xlsx +0 -0
  147. package/treb-format/package.json +8 -0
  148. package/treb-format/src/format.test.ts +213 -0
  149. package/treb-format/src/format.ts +942 -0
  150. package/treb-format/src/format_cache.ts +199 -0
  151. package/treb-format/src/format_parser.ts +723 -0
  152. package/treb-format/src/index.ts +25 -0
  153. package/treb-format/src/number_format_section.ts +100 -0
  154. package/treb-format/src/value_parser.ts +337 -0
  155. package/treb-grid/package.json +5 -0
  156. package/treb-grid/src/editors/autocomplete.ts +394 -0
  157. package/treb-grid/src/editors/autocomplete_matcher.ts +260 -0
  158. package/treb-grid/src/editors/formula_bar.ts +473 -0
  159. package/treb-grid/src/editors/formula_editor_base.ts +910 -0
  160. package/treb-grid/src/editors/overlay_editor.ts +511 -0
  161. package/treb-grid/src/index.ts +37 -0
  162. package/treb-grid/src/layout/base_layout.ts +2618 -0
  163. package/treb-grid/src/layout/grid_layout.ts +299 -0
  164. package/treb-grid/src/layout/rectangle_cache.ts +86 -0
  165. package/treb-grid/src/render/selection-renderer.ts +414 -0
  166. package/treb-grid/src/render/svg_header_overlay.ts +93 -0
  167. package/treb-grid/src/render/svg_selection_block.ts +187 -0
  168. package/treb-grid/src/render/tile_renderer.ts +2122 -0
  169. package/treb-grid/src/types/annotation.ts +216 -0
  170. package/treb-grid/src/types/border_constants.ts +34 -0
  171. package/treb-grid/src/types/clipboard_data.ts +31 -0
  172. package/treb-grid/src/types/data_model.ts +334 -0
  173. package/treb-grid/src/types/drag_mask.ts +81 -0
  174. package/treb-grid/src/types/grid.ts +7743 -0
  175. package/treb-grid/src/types/grid_base.ts +3644 -0
  176. package/treb-grid/src/types/grid_command.ts +470 -0
  177. package/treb-grid/src/types/grid_events.ts +124 -0
  178. package/treb-grid/src/types/grid_options.ts +97 -0
  179. package/treb-grid/src/types/grid_selection.ts +60 -0
  180. package/treb-grid/src/types/named_range.ts +369 -0
  181. package/treb-grid/src/types/scale-control.ts +202 -0
  182. package/treb-grid/src/types/serialize_options.ts +72 -0
  183. package/treb-grid/src/types/set_range_options.ts +52 -0
  184. package/treb-grid/src/types/sheet.ts +3099 -0
  185. package/treb-grid/src/types/sheet_types.ts +95 -0
  186. package/treb-grid/src/types/tab_bar.ts +464 -0
  187. package/treb-grid/src/types/tile.ts +59 -0
  188. package/treb-grid/src/types/update_flags.ts +75 -0
  189. package/treb-grid/src/util/dom_utilities.ts +44 -0
  190. package/treb-grid/src/util/fontmetrics2.ts +179 -0
  191. package/treb-grid/src/util/ua.ts +104 -0
  192. package/treb-logo.svg +18 -0
  193. package/treb-parser/package.json +5 -0
  194. package/treb-parser/src/csv-parser.ts +122 -0
  195. package/treb-parser/src/index.ts +25 -0
  196. package/treb-parser/src/md-parser.ts +526 -0
  197. package/treb-parser/src/parser-types.ts +397 -0
  198. package/treb-parser/src/parser.test.ts +298 -0
  199. package/treb-parser/src/parser.ts +2673 -0
  200. package/treb-utils/package.json +5 -0
  201. package/treb-utils/src/dispatch.ts +57 -0
  202. package/treb-utils/src/event_source.ts +147 -0
  203. package/treb-utils/src/ievent_source.ts +33 -0
  204. package/treb-utils/src/index.ts +31 -0
  205. package/treb-utils/src/measurement.ts +174 -0
  206. package/treb-utils/src/resizable.ts +160 -0
  207. package/treb-utils/src/scale.ts +137 -0
  208. package/treb-utils/src/serialize_html.ts +124 -0
  209. package/treb-utils/src/template.ts +70 -0
  210. package/treb-utils/src/validate_uri.ts +61 -0
  211. package/tsconfig.json +10 -0
  212. package/tsproject.json +30 -0
  213. package/util/license-plugin-esbuild.js +86 -0
  214. package/util/list-css-vars.sh +46 -0
  215. package/README-esm.md +0 -37
  216. package/treb-bundle.css +0 -2
  217. package/treb-bundle.mjs +0 -15
@@ -0,0 +1,397 @@
1
+ /*
2
+ * This file is part of TREB.
3
+ *
4
+ * TREB is free software: you can redistribute it and/or modify it under the
5
+ * terms of the GNU General Public License as published by the Free Software
6
+ * Foundation, either version 3 of the License, or (at your option) any
7
+ * later version.
8
+ *
9
+ * TREB is distributed in the hope that it will be useful, but WITHOUT ANY
10
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12
+ * details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License along
15
+ * with TREB. If not, see <https://www.gnu.org/licenses/>.
16
+ *
17
+ * Copyright 2022-2023 trebco, llc.
18
+ * info@treb.app
19
+ *
20
+ */
21
+
22
+ /**
23
+ * base type, for common data (atm only ID). id is intended to support
24
+ * a unique ID within the context of a single parse pass. (NOTE: in theory
25
+ * you could use the 'position' field... although that's not present in
26
+ * all cases?)
27
+ */
28
+ export interface BaseUnit {
29
+ id: number;
30
+ }
31
+
32
+ export interface UnitLiteralNumber extends BaseUnit {
33
+ type: 'literal';
34
+ position: number;
35
+ value: number;
36
+ text?: string;
37
+ }
38
+ export interface UnitLiteralString extends BaseUnit {
39
+ type: 'literal';
40
+ position: number;
41
+ value: string;
42
+ text?: string;
43
+ }
44
+ export interface UnitLiteralBoolean extends BaseUnit {
45
+ type: 'literal';
46
+ position: number;
47
+ value: boolean;
48
+ text?: string;
49
+ }
50
+
51
+ /**
52
+ * expression unit representing a literal: string, number, boolean.
53
+ * FIXME: would be nice if we had subtypes so we could specify
54
+ * /
55
+ export interface UnitLiteral extends BaseUnit {
56
+ type: 'literal';
57
+ position: number;
58
+ value: string | boolean | number;
59
+ text?: string;
60
+ }
61
+ */
62
+ export type UnitLiteral = UnitLiteralNumber|UnitLiteralBoolean|UnitLiteralString;
63
+
64
+ /**
65
+ * testing: complex
66
+ */
67
+ export interface UnitComplex extends BaseUnit {
68
+ type: 'complex';
69
+ position: number;
70
+ real: number;
71
+ imaginary: number;
72
+ text?: string;
73
+
74
+ /**
75
+ * this flag takes the place of the old "imaginary" unit type;
76
+ * it's an indication that this unit has been composited, so don't
77
+ * do it again. not sure this is actually needed by the parser... is it?
78
+ */
79
+ composited?: boolean;
80
+ }
81
+
82
+ /* *
83
+ * testing: complex
84
+ * this represents just the imaginary part. it's for internal use and should
85
+ * never be returned as a value.
86
+ * /
87
+ export interface UnitImaginary extends BaseUnit {
88
+ type: 'imaginary';
89
+ position: number;
90
+ value: number;
91
+ text?: string;
92
+ }
93
+ */
94
+
95
+ /**
96
+ * expression unit representing an array of primitive values. array
97
+ * can contain mixed values, and holes. array cannot contain arrays,
98
+ * or any other complex type.
99
+ */
100
+ export interface UnitArray extends BaseUnit {
101
+ type: 'array';
102
+ position: number;
103
+ values: Array < Array <string|boolean|number|undefined> >;
104
+ }
105
+
106
+ /**
107
+ * expression unit representing a missing value, intended for missing
108
+ * arguments in function calls.
109
+ */
110
+ export interface UnitMissing extends BaseUnit {
111
+ type: 'missing';
112
+ }
113
+
114
+ /**
115
+ * expression unit representing an opaque name or identifier.
116
+ */
117
+ export interface UnitIdentifier extends BaseUnit {
118
+ type: 'identifier';
119
+ position: number;
120
+ name: string;
121
+ }
122
+
123
+ /**
124
+ * "structured reference" for offset into named table
125
+ */
126
+ export interface UnitStructuredReference extends BaseUnit {
127
+ type: 'structured-reference';
128
+ label: string;
129
+ position: number;
130
+ table: string;
131
+
132
+ /**
133
+ * row refers to "this row". "all" means all values, including the
134
+ * header. "column" means all values except the header.
135
+ */
136
+ scope: 'row'|'all'|'column';
137
+ column: string;
138
+ }
139
+
140
+ /**
141
+ * expression unit representing a group of units; like parentheses in an
142
+ * expression. intended to prevent precendence reordering of operations.
143
+ */
144
+ export interface UnitGroup extends BaseUnit {
145
+ type: 'group';
146
+ elements: ExpressionUnit[];
147
+
148
+ // this flag indicates whether the group was expressly inserted by
149
+ // the user (true) or generated as part of parsing (false). that
150
+ // information is used when unparsing (reconstructing formula).
151
+
152
+ explicit: boolean;
153
+ }
154
+
155
+ /**
156
+ * expression unit representing a function call: has call and arguments.
157
+ */
158
+ export interface UnitCall extends BaseUnit {
159
+ type: 'call';
160
+ name: string;
161
+ position: number;
162
+ args: ExpressionUnit[];
163
+ }
164
+
165
+ /**
166
+ * this isn't an output type (unless parsing fails), but it's useful
167
+ * to be able to pass these around with the same semantics.
168
+ */
169
+ export interface UnitOperator extends BaseUnit {
170
+ type: 'operator';
171
+ position: number;
172
+ operator: string;
173
+ }
174
+
175
+ /**
176
+ * expression unit representing a binary operation. operations may be
177
+ * re-ordered based on precendence.
178
+ */
179
+ export interface UnitBinary extends BaseUnit {
180
+ type: 'binary';
181
+ left: ExpressionUnit;
182
+ operator: string;
183
+ right: ExpressionUnit;
184
+ position: number; // this is the _operator_ position, since that will be the error
185
+ }
186
+
187
+ /**
188
+ * expression unit representing a unary operation.
189
+ */
190
+ export interface UnitUnary extends BaseUnit {
191
+ type: 'unary';
192
+ operator: string;
193
+ operand: ExpressionUnit;
194
+ position: number;
195
+ }
196
+
197
+ /**
198
+ * expression unit representing a spreadsheet address
199
+ */
200
+ export interface UnitAddress extends BaseUnit {
201
+ type: 'address';
202
+ sheet?: string;
203
+ sheet_id?: number;
204
+ label: string;
205
+ row: number;
206
+ column: number;
207
+ absolute_row?: boolean;
208
+ absolute_column?: boolean;
209
+
210
+ /**
211
+ * this means the row is a relative offset from the current row. this
212
+ * happens if you use R1C1 syntax with square brackets.
213
+ */
214
+ offset_row?: boolean;
215
+
216
+ /**
217
+ * this means the column is a relative offset from the current column.
218
+ * this happens if you use R1C1 syntax with square brackets.
219
+ */
220
+ offset_column?: boolean;
221
+
222
+ /** the formula was originally in R1C1. we probably want to translate it. */
223
+ r1c1?: boolean;
224
+
225
+ position: number;
226
+ }
227
+
228
+ /**
229
+ * expression unit representing a spreadsheet range
230
+ */
231
+ export interface UnitRange extends BaseUnit {
232
+ type: 'range';
233
+ label: string;
234
+ start: UnitAddress;
235
+ end: UnitAddress;
236
+ position: number;
237
+ }
238
+
239
+ export interface UnitDimensionedQuantity extends BaseUnit {
240
+ type: 'dimensioned';
241
+ expression: BaseExpressionUnit; // <!-- does not support recursive DQs
242
+ unit: UnitIdentifier;
243
+ }
244
+
245
+ /**
246
+ * discriminated union. this version allows any expression unit _except_ dimensioned quantity
247
+ */
248
+ export type BaseExpressionUnit =
249
+ | UnitLiteral
250
+ | UnitComplex
251
+ | UnitArray
252
+ | UnitIdentifier
253
+ | UnitCall
254
+ | UnitMissing
255
+ | UnitGroup
256
+ | UnitOperator
257
+ | UnitBinary
258
+ | UnitUnary
259
+ | UnitAddress
260
+ | UnitRange
261
+ | UnitStructuredReference
262
+ ;
263
+
264
+ /**
265
+ * discriminated union for type guards, all types
266
+ */
267
+ export type ExpressionUnit =
268
+ | BaseExpressionUnit
269
+ | UnitDimensionedQuantity;
270
+
271
+ /** list of addresses and ranges in the formula, for graphs */
272
+ export interface DependencyList {
273
+ addresses: { [index: string]: UnitAddress };
274
+ ranges: { [index: string]: UnitRange };
275
+ }
276
+
277
+ /**
278
+ * argument separator type for i18n
279
+ */
280
+ export enum ArgumentSeparatorType {
281
+ Comma = ',',
282
+ Semicolon = ';',
283
+ }
284
+
285
+ /**
286
+ * decimal mark for i18n
287
+ */
288
+ export enum DecimalMarkType {
289
+ Period = '.',
290
+ Comma = ',',
291
+ }
292
+
293
+ /**
294
+ * compound result of a parse operation includes dependency list
295
+ * and an error flag (inverted)
296
+ */
297
+ export interface ParseResult {
298
+ expression?: ExpressionUnit;
299
+ valid: boolean;
300
+ error_position?: number;
301
+ error?: string;
302
+ dependencies: DependencyList;
303
+ separator?: string;
304
+ decimal_mark?: string;
305
+ full_reference_list?: Array<UnitRange | UnitAddress | UnitIdentifier | UnitStructuredReference>;
306
+ }
307
+
308
+ //
309
+
310
+ export interface ParserFlags {
311
+
312
+ /**
313
+ * flag: support spreadsheet addresses (e.g. "A1"). this is the default,
314
+ * as it's useful in spreadsheets. however if we want to use the parser
315
+ * non-spreadsheet things, it might be preferable to treat things that look
316
+ * like spreadsheet addresses as tokens instead.
317
+ *
318
+ * this is default so it won't break existing behavior.
319
+ */
320
+ spreadsheet_semantics: boolean,
321
+
322
+ /**
323
+ * flag: support expressions with units, like `3mm` or `=3mm + 2in`.
324
+ * this is for parametric modeling. testing/dev atm.
325
+ */
326
+ dimensioned_quantities: boolean,
327
+
328
+ /**
329
+ * support fractions. this is kind of a weird edge case, mostly it should
330
+ * be handled by the value parser. (actually there might be some need for
331
+ * separate parsing with dimensioned quantities).
332
+ *
333
+ * in any case, if you type `=1/2` that should be a binary expression.
334
+ * if you type `=3 1/2`, though, that means 3.5 and we need to treat it
335
+ * as such.
336
+ *
337
+ * rules:
338
+ *
339
+ * - must be a binary "/" (divide) operation, with integer operands.
340
+ * - must be [literal integer] [fraction] where the interval must be one space.
341
+ * - can be negated (e.g. "-3 1/2", so that makes things more complicated.
342
+ * - if we do translate, translate hard so this becomes a literal number.
343
+ *
344
+ * ...default? since we didn't support this before, we could leave it
345
+ * off for now. needs some more testing.
346
+ *
347
+ */
348
+ fractions: boolean,
349
+
350
+ /**
351
+ * support R1C1 addressing. we support absolute (`R2C3`) and relative
352
+ * (R[-1]C[0]) addresses. can we squeeze this into the existing address
353
+ * structure, or do we need a new structure? (...)
354
+ */
355
+ r1c1: boolean,
356
+
357
+
358
+ /* *
359
+ * what if we do want =1/2 to be a fraction? more importantly, if we are
360
+ * using dimensioned quantities we might want =1/2C to be 0.5C, as opposed
361
+ * to a binary operation =1 / (2C)
362
+ *
363
+ * ...
364
+ *
365
+ * actually now that I think about it, that's equivalent. I was worred about
366
+ * the concept of 1 / (2C) but logically that's the same as 2C / 4C^2 (multiply
367
+ * numerator and denominator by denominator)) which is === (1/2)C. basically
368
+ * as long as you only have one value with a dimension/unit, then division
369
+ * and multiplication are a wash. it's only a concern when you have two
370
+ * values with dimensions/units.
371
+ *
372
+ * so essentially this isn't necessary except for representation, which can
373
+ * be handled separately.
374
+ *
375
+ * ALTHOUGH, if you do that, you have to do the math before you do any
376
+ * unit conversion. because otherwise the ratios get screwed up.
377
+ *
378
+ */
379
+ // aggressive_fractions: false,
380
+
381
+ /* *
382
+ * flag: support complex numbers. it might be useful to turn this off if it
383
+ * conflicts with dimensioned quantities (it doesn't, really, there's no i unit).
384
+ */
385
+ // complex_numbers: true,
386
+
387
+ }
388
+
389
+ export interface RenderOptions {
390
+ offset: { rows: number; columns: number };
391
+ missing: string;
392
+ convert_decimal: DecimalMarkType;
393
+ convert_argument_separator: ArgumentSeparatorType;
394
+ convert_imaginary_number: 'i'|'j';
395
+ long_structured_references: boolean;
396
+ table_name: string;
397
+ }
@@ -0,0 +1,298 @@
1
+ /*
2
+ * This file is part of TREB.
3
+ *
4
+ * TREB is free software: you can redistribute it and/or modify it under the
5
+ * terms of the GNU General Public License as published by the Free Software
6
+ * Foundation, either version 3 of the License, or (at your option) any
7
+ * later version.
8
+ *
9
+ * TREB is distributed in the hope that it will be useful, but WITHOUT ANY
10
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12
+ * details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License along
15
+ * with TREB. If not, see <https://www.gnu.org/licenses/>.
16
+ *
17
+ * Copyright 2022-2023 trebco, llc.
18
+ * info@treb.app
19
+ *
20
+ */
21
+
22
+ // import { Parser, UnitLiteral, UnitBinary, UnitUnary, DecimalMarkType, UnitCall, ArgumentSeparatorType } from '../';
23
+ import { Parser } from './parser';
24
+ import { ArgumentSeparatorType,
25
+ UnitLiteral, UnitBinary, UnitUnary, DecimalMarkType, UnitCall } from './parser-types';
26
+
27
+ const parser = new Parser();
28
+
29
+ test('constructor', () => {
30
+ expect(typeof parser).toBe('object');
31
+ });
32
+
33
+ describe('basic parsing', () => {
34
+
35
+ test('3 + 4', () => {
36
+ const result = parser.Parse('3 + 4');
37
+ expect(result).toBeDefined();
38
+ expect(result.valid).toBeTruthy();
39
+ });
40
+
41
+ test('/ 2', () => {
42
+ const result = parser.Parse('/ 2');
43
+ expect(result).toBeDefined();
44
+ expect(result.valid).toBeFalsy();
45
+ });
46
+
47
+ });
48
+
49
+ describe('parsing/rendering', () => {
50
+
51
+ const expression = '2.2 + (3 / foo(bar("1"), 8))';
52
+ test(expression, () => {
53
+ const result = parser.Parse(expression);
54
+ expect(result.valid).toBeTruthy();
55
+ expect(result.expression).toBeDefined();
56
+ if (result.expression){
57
+ const rendered = parser.Render(result.expression);
58
+ expect(rendered).toEqual(expression);
59
+ }
60
+ });
61
+
62
+ test('converting separators', () => {
63
+ const result = parser.Parse(expression);
64
+ expect(result.valid).toBeTruthy();
65
+ expect(result.expression).toBeDefined();
66
+ if (result.expression){
67
+ const rendered = parser.Render(result.expression,
68
+ undefined, undefined, DecimalMarkType.Comma, ArgumentSeparatorType.Semicolon);
69
+ expect(rendered).toEqual('2,2 + (3 / foo(bar("1"); 8))');
70
+ }
71
+ });
72
+
73
+ });
74
+
75
+ describe('number parsing', () => {
76
+
77
+ const decimals = [1, 1.11, 2.2343, 123819238, -6, -7.77, -0.00012];
78
+
79
+ decimals.forEach((decimal) => {
80
+ const as_string = decimal.toString();
81
+ test(as_string, () => {
82
+ const result = parser.Parse(as_string);
83
+ expect(result).toBeDefined();
84
+ expect(result.expression).toBeDefined();
85
+ if (result.expression) {
86
+ expect(result.expression.type).toBe('literal');
87
+ expect((result.expression as UnitLiteral).value).toBeCloseTo(decimal);
88
+ }
89
+ });
90
+ });
91
+
92
+ test('2.2e-7', () => {
93
+ const result = parser.Parse('2.2e-7');
94
+ expect(result).toBeDefined();
95
+ expect(result.expression).toBeDefined();
96
+ if (result.expression) {
97
+ expect(result.expression.type).toBe('literal');
98
+ expect((result.expression as UnitLiteral).value).toBeCloseTo(2.2e-7);
99
+ }
100
+ });
101
+
102
+ test('-1.123e8', () => {
103
+ const result = parser.Parse('-1.123e8');
104
+ expect(result).toBeDefined();
105
+ expect(result.expression).toBeDefined();
106
+ if (result.expression) {
107
+ expect(result.expression.type).toBe('literal');
108
+ expect((result.expression as UnitLiteral).value).toBeCloseTo(-1.123e8);
109
+ }
110
+ });
111
+
112
+ test('33.33%', () => {
113
+ const result = parser.Parse('33.33%');
114
+ expect(result).toBeDefined();
115
+ expect(result.expression).toBeDefined();
116
+ if (result.expression) {
117
+ expect(result.expression.type).toBe('literal');
118
+ expect((result.expression as UnitLiteral).value).toBeCloseTo(.3333);
119
+ }
120
+ });
121
+
122
+ });
123
+
124
+ describe('comma decimal parsing', () => {
125
+
126
+ test('1,23', () => {
127
+ parser.decimal_mark = DecimalMarkType.Comma;
128
+ const result = parser.Parse('1,23');
129
+ parser.decimal_mark = DecimalMarkType.Period;
130
+ expect(result).toBeDefined();
131
+ expect(result.expression).toBeDefined();
132
+ if (result.expression) {
133
+ expect(result.expression.type).toBe('literal');
134
+ expect((result.expression as UnitLiteral).value).toBeCloseTo(1.23);
135
+ }
136
+ });
137
+
138
+ test('-2231,909', () => {
139
+ parser.decimal_mark = DecimalMarkType.Comma;
140
+ const result = parser.Parse('-2231,909');
141
+ parser.decimal_mark = DecimalMarkType.Period;
142
+ expect(result).toBeDefined();
143
+ expect(result.expression).toBeDefined();
144
+ if (result.expression) {
145
+ expect(result.expression.type).toBe('literal');
146
+ expect((result.expression as UnitLiteral).value).toBeCloseTo(-2231.909);
147
+ }
148
+ });
149
+ });
150
+
151
+ describe('unary operators', () => {
152
+
153
+ test('2 + -3', () => {
154
+ const result = parser.Parse('2 + -3');
155
+ expect(result).toBeDefined();
156
+ expect(result.expression).toBeDefined();
157
+ if (result.expression) {
158
+ expect(result.expression.type).toBe('binary');
159
+ const right = (result.expression as UnitBinary).right;
160
+ expect(right).toBeDefined();
161
+ if (right){
162
+ expect(right.type).toBe('unary');
163
+ const unary = (right as UnitUnary);
164
+ expect(unary.operator).toBe('-');
165
+ expect(unary.operand.type).toBe('literal');
166
+ expect((unary.operand as UnitLiteral).value).toBeCloseTo(3);
167
+ }
168
+ }
169
+ });
170
+
171
+ test('op() / +3', () => {
172
+ const result = parser.Parse('op() / +3');
173
+ expect(result).toBeDefined();
174
+ expect(result.expression).toBeDefined();
175
+ if (result.expression) {
176
+ expect(result.expression.type).toBe('binary');
177
+ const right = (result.expression as UnitBinary).right;
178
+ expect(right).toBeDefined();
179
+ if (right){
180
+ expect(right.type).toBe('unary');
181
+ const unary = (right as UnitUnary);
182
+ expect(unary.operator).toBe('+');
183
+ expect(unary.operand.type).toBe('literal');
184
+ expect((unary.operand as UnitLiteral).value).toBeCloseTo(3);
185
+ }
186
+ }
187
+ });
188
+ });
189
+
190
+ describe('binary operators', () => {
191
+
192
+ test('10 * 8', () => {
193
+ const result = parser.Parse('10 * 8');
194
+ expect(result).toBeDefined();
195
+ expect(result.expression).toBeDefined();
196
+ if (result.expression) {
197
+ expect(result.expression.type).toBe('binary');
198
+ const binary = result.expression as UnitBinary;
199
+ expect(binary.operator).toBe('*');
200
+ expect((binary.left as UnitLiteral).value).toBe(10);
201
+ expect((binary.right as UnitLiteral).value).toBe(8);
202
+ }
203
+ });
204
+
205
+ });
206
+
207
+ describe('grouping/ordering', () => {
208
+ test('(2 / (1 + (2 * 3))) * 4', () => {
209
+ const result = parser.Parse('(2 / (1 + (2 * 3))) * 4');
210
+ expect(result).toBeDefined();
211
+ expect(result.expression).toBeDefined();
212
+ if (result.expression){
213
+ expect(result.expression.type).toBe('binary');
214
+ const binary = result.expression as UnitBinary;
215
+ expect(binary.right.type).toBe('literal');
216
+ expect((binary.right as UnitLiteral).value).toBe(4);
217
+ expect(binary.left.type).toBe('group');
218
+ }
219
+ });
220
+ });
221
+
222
+ describe('function calls', () => {
223
+
224
+ test('foo()', () => {
225
+ const result = parser.Parse('foo()');
226
+ expect(result).toBeDefined();
227
+ expect(result.expression).toBeDefined();
228
+ if (result.expression) {
229
+ expect(result.expression.type).toBe('call');
230
+ const call = result.expression as UnitCall;
231
+ expect(call.name).toBe('foo');
232
+ expect(call.args.length).toBe(0);
233
+ }
234
+ });
235
+
236
+ test('oof(1, "bar", 3.3)', () => {
237
+ const result = parser.Parse('oof(1, "bar", 3.3)');
238
+ expect(result).toBeDefined();
239
+ expect(result.expression).toBeDefined();
240
+ if (result.expression) {
241
+ expect(result.expression.type).toBe('call');
242
+ const call = result.expression as UnitCall;
243
+ expect(call.name).toBe('oof');
244
+ expect(call.args.length).toBe(3);
245
+ if (call.args.length === 3){
246
+ expect(call.args[0].type).toBe('literal');
247
+ expect((call.args[0] as UnitLiteral).value).toBe(1);
248
+ expect(call.args[1].type).toBe('literal');
249
+ expect((call.args[1] as UnitLiteral).value).toBe('bar');
250
+ expect(call.args[2].type).toBe('literal');
251
+ expect((call.args[2] as UnitLiteral).value).toBe(3.3);
252
+ }
253
+ }
254
+ });
255
+
256
+ });
257
+
258
+ describe('addresses', () => {
259
+ test('=A1 + $B2 - C$3 - $ZZ$40', () => {
260
+ const result = parser.Parse('=A1 + $B2 - C$3 - $ZZ$40');
261
+ expect(result).toBeDefined();
262
+ expect(result.expression).toBeDefined();
263
+ if (result.expression) {
264
+ expect(parser.Render(result.expression)).toBe('A1 + $B2 - C$3 - $ZZ$40');
265
+ }
266
+ });
267
+ });
268
+
269
+ describe('semicolon-separated arguments', () => {
270
+
271
+ test('xfoo(1; "xbar"; 3,33)', () => {
272
+ parser.decimal_mark = DecimalMarkType.Comma;
273
+ parser.argument_separator = ArgumentSeparatorType.Semicolon;
274
+ const result = parser.Parse('xfoo(1; "xbar"; 3,33)');
275
+ parser.decimal_mark = DecimalMarkType.Period;
276
+ parser.argument_separator = ArgumentSeparatorType.Comma;
277
+
278
+ expect(result).toBeDefined();
279
+ expect(result.expression).toBeDefined();
280
+ if (result.expression) {
281
+ expect(result.expression.type).toBe('call');
282
+ const call = result.expression as UnitCall;
283
+ expect(call.name).toBe('xfoo');
284
+ expect(call.args.length).toBe(3);
285
+ if (call.args.length === 3){
286
+ expect(call.args[0].type).toBe('literal');
287
+ expect((call.args[0] as UnitLiteral).value).toBe(1);
288
+ expect(call.args[1].type).toBe('literal');
289
+ expect((call.args[1] as UnitLiteral).value).toBe('xbar');
290
+ expect(call.args[2].type).toBe('literal');
291
+ expect((call.args[2] as UnitLiteral).value).toBeCloseTo(3.33);
292
+ }
293
+ }
294
+ });
295
+
296
+ });
297
+
298
+