@bikky/replication 1.0.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.
Files changed (140) hide show
  1. package/Constants/Errors.d.ts +27 -0
  2. package/Constants/Errors.js +75 -0
  3. package/Constants/Logging.d.ts +17 -0
  4. package/Constants/Logging.js +97 -0
  5. package/Constants/ReplicableRegistry.d.ts +37 -0
  6. package/Constants/ReplicableRegistry.js +234 -0
  7. package/Constants/SerialisationTypes.d.ts +82 -0
  8. package/Constants/SerialisationTypes.js +160 -0
  9. package/Constants/SourceMaps.d.ts +10 -0
  10. package/Constants/SourceMaps.js +12 -0
  11. package/Constants/TraversalStep.d.ts +5 -0
  12. package/Constants/TraversalStep.js +2 -0
  13. package/Constants/Versions.d.ts +15 -0
  14. package/Constants/Versions.js +63 -0
  15. package/Expressions/Compiler/BuiltinGrammar.d.ts +234 -0
  16. package/Expressions/Compiler/BuiltinGrammar.js +446 -0
  17. package/Expressions/Compiler/ExpressionGrammar.d.ts +89 -0
  18. package/Expressions/Compiler/ExpressionGrammar.js +70 -0
  19. package/Expressions/Compiler/Parser.d.ts +56 -0
  20. package/Expressions/Compiler/Parser.js +314 -0
  21. package/Expressions/Compiler/Tokenizer.d.ts +52 -0
  22. package/Expressions/Compiler/Tokenizer.js +222 -0
  23. package/Expressions/Compiler/__tests__/Replicable.Expressions.Parser.test.d.ts +1 -0
  24. package/Expressions/Compiler/__tests__/Replicable.Expressions.Parser.test.js +516 -0
  25. package/Expressions/Compiler/__tests__/Replicable.Expressions.Tokenizer.test.d.ts +1 -0
  26. package/Expressions/Compiler/__tests__/Replicable.Expressions.Tokenizer.test.js +68 -0
  27. package/Expressions/CreateEvaluator.d.ts +4 -0
  28. package/Expressions/CreateEvaluator.js +85 -0
  29. package/Expressions/EvaluatorChain.d.ts +19 -0
  30. package/Expressions/EvaluatorChain.js +137 -0
  31. package/Expressions/EvaluatorSteps.d.ts +19 -0
  32. package/Expressions/EvaluatorSteps.js +12 -0
  33. package/Expressions/EvaluatorString.d.ts +21 -0
  34. package/Expressions/EvaluatorString.js +26 -0
  35. package/Expressions/Expression.d.ts +36 -0
  36. package/Expressions/Expression.js +147 -0
  37. package/Expressions/Traverser.d.ts +28 -0
  38. package/Expressions/Traverser.js +348 -0
  39. package/Expressions/TypeRegistry/Accessors.d.ts +26 -0
  40. package/Expressions/TypeRegistry/Accessors.js +58 -0
  41. package/Expressions/TypeRegistry/ChainCollections.d.ts +51 -0
  42. package/Expressions/TypeRegistry/ChainCollections.js +134 -0
  43. package/Expressions/TypeRegistry/ChainTypes.d.ts +23 -0
  44. package/Expressions/TypeRegistry/ChainTypes.js +46 -0
  45. package/Expressions/TypeRegistry/CustomAPI.d.ts +36 -0
  46. package/Expressions/TypeRegistry/CustomAPI.js +181 -0
  47. package/Expressions/TypeRegistry/Primitive.d.ts +19 -0
  48. package/Expressions/TypeRegistry/Primitive.js +47 -0
  49. package/Expressions/TypeRegistry/Registry.d.ts +27 -0
  50. package/Expressions/TypeRegistry/Registry.js +270 -0
  51. package/Expressions/TypeRegistry/ReplAPI.d.ts +41 -0
  52. package/Expressions/TypeRegistry/ReplAPI.js +220 -0
  53. package/Expressions/TypeRegistry/Scope.d.ts +24 -0
  54. package/Expressions/TypeRegistry/Scope.js +44 -0
  55. package/Expressions/TypeRegistry/Types.d.ts +23 -0
  56. package/Expressions/TypeRegistry/Types.js +1 -0
  57. package/Expressions/TypeRegistry/__tests__/Replicable.Expressions.Accessors.test.d.ts +1 -0
  58. package/Expressions/TypeRegistry/__tests__/Replicable.Expressions.Accessors.test.js +31 -0
  59. package/Expressions/__tests__/ExpressionExamples.d.ts +28 -0
  60. package/Expressions/__tests__/ExpressionExamples.js +50 -0
  61. package/Expressions/__tests__/Replicable.Expressions.Expressions.test.d.ts +1 -0
  62. package/Expressions/__tests__/Replicable.Expressions.Expressions.test.js +166 -0
  63. package/IDPool.d.ts +18 -0
  64. package/IDPool.data.d.ts +17 -0
  65. package/IDPool.js +139 -0
  66. package/License.txt +1 -0
  67. package/Main.d.ts +13 -0
  68. package/Main.js +13 -0
  69. package/Networking.d.ts +60 -0
  70. package/Networking.js +626 -0
  71. package/Replicatable.d.ts +66 -0
  72. package/Replicatable.js +123 -0
  73. package/Tracking/Buffable.d.ts +68 -0
  74. package/Tracking/Buffable.js +194 -0
  75. package/Tracking/Class.d.ts +97 -0
  76. package/Tracking/Class.js +221 -0
  77. package/Tracking/Functions.d.ts +14 -0
  78. package/Tracking/Functions.js +27 -0
  79. package/Tracking/GlobalGroup.d.ts +5 -0
  80. package/Tracking/GlobalGroup.js +39 -0
  81. package/Tracking/Property.d.ts +95 -0
  82. package/Tracking/Property.js +125 -0
  83. package/Tracking/Types.d.ts +33 -0
  84. package/Tracking/Types.js +1 -0
  85. package/Tracking/__tests__/Replicable.Tracking.Decorator.test.d.ts +1 -0
  86. package/Tracking/__tests__/Replicable.Tracking.Decorator.test.js +151 -0
  87. package/Tracking/__tests__/Replicable.Tracking.Deserialisation.test.d.ts +1 -0
  88. package/Tracking/__tests__/Replicable.Tracking.Deserialisation.test.js +253 -0
  89. package/Tracking/__tests__/Replicable.Tracking.MixinSchemaGeneration.test.d.ts +1 -0
  90. package/Tracking/__tests__/Replicable.Tracking.MixinSchemaGeneration.test.js +135 -0
  91. package/Tracking/__tests__/Replicable.Tracking.Struct.test.d.ts +1 -0
  92. package/Tracking/__tests__/Replicable.Tracking.Struct.test.js +66 -0
  93. package/Tracking/__tests__/Replicable.Tracking.Type.test.d.ts +1 -0
  94. package/Tracking/__tests__/Replicable.Tracking.Type.test.js +67 -0
  95. package/Transformers/Configurer.d.ts +39 -0
  96. package/Transformers/Configurer.js +415 -0
  97. package/Transformers/Constructor.d.ts +12 -0
  98. package/Transformers/Constructor.js +44 -0
  99. package/Transformers/Definitions.d.ts +102 -0
  100. package/Transformers/Definitions.js +626 -0
  101. package/Transformers/Loader.d.ts +45 -0
  102. package/Transformers/Loader.js +350 -0
  103. package/Transformers/Progress.d.ts +32 -0
  104. package/Transformers/Progress.js +429 -0
  105. package/Transformers/Reference.d.ts +37 -0
  106. package/Transformers/Reference.js +212 -0
  107. package/Transformers/SchemaGenerator.d.ts +102 -0
  108. package/Transformers/SchemaGenerator.js +564 -0
  109. package/Transformers/Serialiser.d.ts +31 -0
  110. package/Transformers/Serialiser.js +366 -0
  111. package/Transformers/Utils.d.ts +33 -0
  112. package/Transformers/Utils.js +287 -0
  113. package/Transformers/__tests__/Examples.d.ts +168 -0
  114. package/Transformers/__tests__/Examples.js +263 -0
  115. package/Transformers/__tests__/Replicable.Transformers.Definitions.test.d.ts +1 -0
  116. package/Transformers/__tests__/Replicable.Transformers.Definitions.test.js +457 -0
  117. package/Transformers/__tests__/Replicable.Transformers.Loader.test.d.ts +1 -0
  118. package/Transformers/__tests__/Replicable.Transformers.Loader.test.js +339 -0
  119. package/Transformers/__tests__/Replicable.Transformers.Progress.test.d.ts +1 -0
  120. package/Transformers/__tests__/Replicable.Transformers.Progress.test.js +256 -0
  121. package/Transformers/__tests__/Replicable.Transformers.Reference.test.d.ts +1 -0
  122. package/Transformers/__tests__/Replicable.Transformers.Reference.test.js +167 -0
  123. package/Transformers/__tests__/Replicable.Transformers.SchemaGenerator.test.d.ts +1 -0
  124. package/Transformers/__tests__/Replicable.Transformers.SchemaGenerator.test.js +400 -0
  125. package/Transformers/__tests__/Replicable.Transformers.SchemaGeneratorOutput.test.d.ts +1 -0
  126. package/Transformers/__tests__/Replicable.Transformers.SchemaGeneratorOutput.test.js +441 -0
  127. package/Transformers/__tests__/Replicable.Transformers.Serialiser.test.d.ts +1 -0
  128. package/Transformers/__tests__/Replicable.Transformers.Serialiser.test.js +320 -0
  129. package/Transformers/__tests__/Replicable.Transformers.Utils.test.d.ts +1 -0
  130. package/Transformers/__tests__/Replicable.Transformers.Utils.test.js +534 -0
  131. package/__tests__/Replicable.Expressions.test.d.ts +1 -0
  132. package/__tests__/Replicable.Expressions.test.js +166 -0
  133. package/__tests__/Replicable.IDPool.test.d.ts +1 -0
  134. package/__tests__/Replicable.IDPool.test.js +11 -0
  135. package/__tests__/Replicable.ReplicableRegistry.test.d.ts +1 -0
  136. package/__tests__/Replicable.ReplicableRegistry.test.js +154 -0
  137. package/__tests__/Replicable.Serialisation.test.d.ts +1 -0
  138. package/__tests__/Replicable.Serialisation.test.js +283 -0
  139. package/package.json +14 -0
  140. package/tsconfig.json +19 -0
@@ -0,0 +1,516 @@
1
+ import { describe, expect, test } from "vitest";
2
+ import { TokenType } from "../Tokenizer.js";
3
+ import { CreateASTFromString, ExpressionParser, MatchGrammar, MatchRepeatingRule, MatchRule } from "../Parser.js";
4
+ import { GetVersionIndex, Versions } from "../../../Constants/Versions.js";
5
+ import { ExpressionGrammar } from "../ExpressionGrammar.js";
6
+ import { BikPath } from "@bikky/path";
7
+ import "../BuiltinGrammar.js";
8
+ var NodeType = ExpressionGrammar.NodeType;
9
+ describe(" 1. Parsing Functions", () => {
10
+ let version = Versions.v1_0_0;
11
+ let sourceFile = BikPath.getCurrentFilepath();
12
+ let versionIndex = GetVersionIndex(version);
13
+ let singleText = "value";
14
+ // let single = TokenizeExpression(singleText, version);
15
+ let multipartText = "value.second";
16
+ // let multipart = TokenizeExpression(multipartText, version);
17
+ let fooText = "value()";
18
+ // let foo = TokenizeExpression(fooText, version);
19
+ let fooParamsText = "value(first, second)";
20
+ // let fooParams = TokenizeExpression(fooParamsText, version);
21
+ let castText = "value:=number";
22
+ // let cast = TokenizeExpression(castText, version);
23
+ let castMultipartText = "value:=number.second";
24
+ // let castMultipart = TokenizeExpression(castMultipartText, version);
25
+ let multipartCastText = "value.second:=number";
26
+ // let multipartCast = TokenizeExpression(multipartCastText, version);
27
+ let castRule = ExpressionGrammar.getRule(versionIndex, NodeType.FORCE_CAST);
28
+ let multipartRule = ExpressionGrammar.getRule(versionIndex, NodeType.MEMBER_ACCESS);
29
+ let fooRule = ExpressionGrammar.getRule(versionIndex, NodeType.FUNCTION_CALL);
30
+ let expressionRule = ExpressionGrammar.getRule(versionIndex, NodeType.EXPRESSION);
31
+ function MakeNextMatchDetails(text) {
32
+ return {
33
+ parser: new ExpressionParser(version, text, sourceFile),
34
+ debugTabs: "",
35
+ extraTypes: []
36
+ };
37
+ }
38
+ function MakePartialNode(type) {
39
+ return {
40
+ type: type,
41
+ debugName: NodeType[type],
42
+ values: {}
43
+ };
44
+ }
45
+ test(" 1. MatchRule Single", () => {
46
+ let details = MakeNextMatchDetails(singleText);
47
+ let result = MatchRule(details, expressionRule.rules[0], MakePartialNode(NodeType.EXPRESSION), []);
48
+ expect(result).not.toBeUndefined();
49
+ expect(result).toContainAtLeast({
50
+ type: NodeType.EXPRESSION,
51
+ values: {
52
+ expression: {
53
+ type: TokenType.IDENTIFIER,
54
+ data: "value"
55
+ }
56
+ }
57
+ });
58
+ expect(details.parser.currentNodeIndex).toBe(1);
59
+ });
60
+ test(" 2. MatchRule Multipart", () => {
61
+ let details = MakeNextMatchDetails(multipartText);
62
+ let result = MatchRule(details, multipartRule.rules[0], MakePartialNode(NodeType.MEMBER_ACCESS), []);
63
+ expect(result).toContainAtLeast({
64
+ type: NodeType.MEMBER_ACCESS,
65
+ values: {
66
+ context: {
67
+ type: TokenType.IDENTIFIER,
68
+ data: "value"
69
+ }
70
+ }
71
+ });
72
+ expect(details.parser.currentNodeIndex).toBe(1);
73
+ result = MatchRule(details, multipartRule.rules[1], result, []);
74
+ expect(result).not.toBeUndefined();
75
+ expect(details.parser.currentNodeIndex).toBe(2);
76
+ result = MatchRule(details, multipartRule.rules[2], result, []);
77
+ expect(result).toContainAtLeast({
78
+ type: NodeType.MEMBER_ACCESS,
79
+ values: {
80
+ context: {
81
+ type: TokenType.IDENTIFIER,
82
+ data: "value"
83
+ },
84
+ memberName: {
85
+ type: TokenType.IDENTIFIER,
86
+ data: "second"
87
+ }
88
+ }
89
+ });
90
+ expect(details.parser.currentNodeIndex).toBe(3);
91
+ });
92
+ test(" 3. MatchGrammar Single", () => {
93
+ let details = MakeNextMatchDetails(singleText);
94
+ let result = MatchGrammar(details, NodeType.EXPRESSION, []);
95
+ expect(result).toContainAtLeast({
96
+ type: NodeType.EXPRESSION,
97
+ values: {
98
+ expression: {
99
+ type: TokenType.IDENTIFIER,
100
+ data: "value"
101
+ }
102
+ }
103
+ });
104
+ expect(details.parser.currentNodeIndex).toBe(1);
105
+ });
106
+ test(" 4. MatchGrammar Multipart", () => {
107
+ let details = MakeNextMatchDetails(multipartText);
108
+ let result = MatchGrammar(details, NodeType.EXPRESSION, []);
109
+ expect(result).toContainAtLeast({
110
+ type: NodeType.EXPRESSION,
111
+ values: {
112
+ expression: {
113
+ type: NodeType.MEMBER_ACCESS,
114
+ values: {
115
+ context: {
116
+ type: TokenType.IDENTIFIER,
117
+ data: "value"
118
+ },
119
+ memberName: {
120
+ type: TokenType.IDENTIFIER,
121
+ data: "second"
122
+ }
123
+ }
124
+ }
125
+ }
126
+ });
127
+ expect(details.parser.currentNodeIndex).toBe(3);
128
+ });
129
+ test(" 5. MatchRule Function Call", () => {
130
+ let details = MakeNextMatchDetails(fooText);
131
+ let result = MatchRule(details, fooRule.rules[0], MakePartialNode(NodeType.FUNCTION_CALL), []);
132
+ expect(result).toContainAtLeast({
133
+ type: NodeType.FUNCTION_CALL,
134
+ values: {
135
+ name: {
136
+ type: TokenType.IDENTIFIER,
137
+ data: "value"
138
+ }
139
+ }
140
+ });
141
+ expect(details.parser.currentNodeIndex).toBe(1);
142
+ result = MatchRule(details, fooRule.rules[1], result, []);
143
+ expect(result).not.toBeUndefined();
144
+ expect(details.parser.currentNodeIndex).toBe(2);
145
+ result = MatchRepeatingRule(details, fooRule.rules[2], result, []);
146
+ expect(result).toContainAtLeast({
147
+ type: NodeType.FUNCTION_CALL,
148
+ values: {
149
+ name: {
150
+ type: TokenType.IDENTIFIER,
151
+ data: "value"
152
+ }
153
+ }
154
+ });
155
+ expect(details.parser.currentNodeIndex).toBe(2);
156
+ });
157
+ test(" 6. MatchRule Function with Parameters", () => {
158
+ let details = MakeNextMatchDetails(fooParamsText);
159
+ let result = MatchRule(details, fooRule.rules[0], MakePartialNode(NodeType.FUNCTION_CALL), []);
160
+ expect(result).toContainAtLeast({
161
+ type: NodeType.FUNCTION_CALL,
162
+ values: {
163
+ name: {
164
+ type: TokenType.IDENTIFIER,
165
+ data: "value"
166
+ }
167
+ }
168
+ });
169
+ expect(details.parser.currentNodeIndex).toBe(1);
170
+ result = MatchRule(details, fooRule.rules[1], result, []);
171
+ expect(result).not.toBeUndefined();
172
+ expect(details.parser.currentNodeIndex).toBe(2);
173
+ result = MatchRepeatingRule(details, fooRule.rules[2], result, []);
174
+ expect(result).toContainAtLeast({
175
+ type: NodeType.FUNCTION_CALL,
176
+ values: {
177
+ name: {
178
+ type: TokenType.IDENTIFIER,
179
+ data: "value"
180
+ },
181
+ arguments: [{
182
+ type: NodeType.EXPRESSION,
183
+ values: {
184
+ expression: {
185
+ type: TokenType.IDENTIFIER,
186
+ data: "first"
187
+ }
188
+ }
189
+ }, {
190
+ type: NodeType.EXPRESSION,
191
+ values: {
192
+ expression: {
193
+ type: TokenType.IDENTIFIER,
194
+ data: "second"
195
+ }
196
+ }
197
+ }]
198
+ }
199
+ });
200
+ expect(details.parser.currentNodeIndex).toBe(6);
201
+ });
202
+ test(" 7. MatchRule Cast", () => {
203
+ let details = MakeNextMatchDetails(castText);
204
+ let result = MatchRule(details, castRule.rules[0], MakePartialNode(NodeType.FORCE_CAST), []);
205
+ expect(result).toContainAtLeast({
206
+ type: NodeType.FORCE_CAST,
207
+ values: {
208
+ expression: {
209
+ type: TokenType.IDENTIFIER,
210
+ data: "value"
211
+ }
212
+ }
213
+ });
214
+ expect(details.parser.currentNodeIndex).toBe(1);
215
+ result = MatchRule(details, castRule.rules[1], result, []);
216
+ result = MatchRule(details, castRule.rules[2], result, []);
217
+ result = MatchRule(details, castRule.rules[3], result, []);
218
+ expect(result).toContainAtLeast({
219
+ type: NodeType.FORCE_CAST,
220
+ values: {
221
+ expression: {
222
+ type: TokenType.IDENTIFIER,
223
+ data: "value"
224
+ },
225
+ castType: {
226
+ type: TokenType.IDENTIFIER,
227
+ data: "number"
228
+ }
229
+ }
230
+ });
231
+ expect(details.parser.currentNodeIndex).toBe(4);
232
+ });
233
+ test(" 8. MatchRule Cast Multipart", () => {
234
+ let details = MakeNextMatchDetails(castMultipartText);
235
+ let result = MatchRule(details, multipartRule.rules[0], MakePartialNode(NodeType.MEMBER_ACCESS), []);
236
+ expect(result).toContainAtLeast({
237
+ type: NodeType.MEMBER_ACCESS,
238
+ values: {
239
+ context: {
240
+ type: NodeType.FORCE_CAST,
241
+ values: {
242
+ expression: {
243
+ type: TokenType.IDENTIFIER,
244
+ data: "value"
245
+ },
246
+ castType: {
247
+ type: TokenType.IDENTIFIER,
248
+ data: "number"
249
+ }
250
+ }
251
+ }
252
+ }
253
+ });
254
+ expect(details.parser.currentNodeIndex).toBe(4);
255
+ result = MatchRule(details, multipartRule.rules[1], result, []);
256
+ result = MatchRule(details, multipartRule.rules[2], result, []);
257
+ expect(result).toContainAtLeast({
258
+ type: NodeType.MEMBER_ACCESS,
259
+ values: {
260
+ context: {
261
+ type: NodeType.FORCE_CAST,
262
+ values: {
263
+ expression: {
264
+ type: TokenType.IDENTIFIER,
265
+ data: "value"
266
+ },
267
+ castType: {
268
+ type: TokenType.IDENTIFIER,
269
+ data: "number"
270
+ }
271
+ }
272
+ },
273
+ memberName: {
274
+ type: TokenType.IDENTIFIER,
275
+ data: "second"
276
+ }
277
+ }
278
+ });
279
+ expect(details.parser.currentNodeIndex).toBe(6);
280
+ });
281
+ test(" 9. MatchRule Multipart Cast", () => {
282
+ let details = MakeNextMatchDetails(multipartCastText);
283
+ let result = MatchRule(details, multipartRule.rules[0], MakePartialNode(NodeType.MEMBER_ACCESS), []);
284
+ expect(result).toContainAtLeast({
285
+ type: NodeType.MEMBER_ACCESS,
286
+ values: {
287
+ context: {
288
+ type: TokenType.IDENTIFIER,
289
+ data: "value"
290
+ }
291
+ }
292
+ });
293
+ expect(details.parser.currentNodeIndex).toBe(1);
294
+ result = MatchRule(details, multipartRule.rules[1], result, []);
295
+ result = MatchRule(details, multipartRule.rules[2], result, []);
296
+ expect(result).toContainAtLeast({
297
+ type: NodeType.MEMBER_ACCESS,
298
+ values: {
299
+ context: {
300
+ type: TokenType.IDENTIFIER,
301
+ data: "value"
302
+ },
303
+ memberName: {
304
+ type: NodeType.FORCE_CAST,
305
+ values: {
306
+ expression: {
307
+ type: TokenType.IDENTIFIER,
308
+ data: "second"
309
+ },
310
+ castType: {
311
+ type: TokenType.IDENTIFIER,
312
+ data: "number"
313
+ }
314
+ }
315
+ }
316
+ }
317
+ });
318
+ expect(details.parser.currentNodeIndex).toBe(6);
319
+ });
320
+ test(" 10. MatchGrammar Function result cast", () => {
321
+ let details = MakeNextMatchDetails("value():=number");
322
+ let result = MatchGrammar(details, NodeType.EXPRESSION, []);
323
+ expect(result).toContainAtLeast({
324
+ type: NodeType.EXPRESSION,
325
+ values: {
326
+ expression: {
327
+ type: NodeType.FORCE_CAST,
328
+ values: {
329
+ expression: {
330
+ type: NodeType.FUNCTION_CALL,
331
+ values: {
332
+ name: {
333
+ type: TokenType.IDENTIFIER,
334
+ data: "value"
335
+ },
336
+ }
337
+ },
338
+ castType: {
339
+ type: TokenType.IDENTIFIER,
340
+ data: "number"
341
+ }
342
+ }
343
+ }
344
+ }
345
+ });
346
+ expect(details.parser.currentNodeIndex).toBe(6);
347
+ });
348
+ test(" 11. MatchGrammar Multipart Cast Function result cast", () => {
349
+ let details = MakeNextMatchDetails("value:=Entity.second():=number");
350
+ let result = MatchGrammar(details, NodeType.EXPRESSION, []);
351
+ expect(result).toContainAtLeast({
352
+ type: NodeType.EXPRESSION,
353
+ values: {
354
+ expression: {
355
+ type: NodeType.MEMBER_ACCESS,
356
+ values: {
357
+ context: {
358
+ type: NodeType.FORCE_CAST,
359
+ values: {
360
+ expression: {
361
+ type: TokenType.IDENTIFIER,
362
+ data: "value"
363
+ },
364
+ castType: {
365
+ type: TokenType.IDENTIFIER,
366
+ data: "Entity"
367
+ }
368
+ }
369
+ },
370
+ memberName: {
371
+ type: NodeType.FORCE_CAST,
372
+ values: {
373
+ expression: {
374
+ type: NodeType.FUNCTION_CALL,
375
+ values: {
376
+ name: {
377
+ type: TokenType.IDENTIFIER,
378
+ data: "second"
379
+ },
380
+ }
381
+ },
382
+ castType: {
383
+ type: TokenType.IDENTIFIER,
384
+ data: "number"
385
+ }
386
+ }
387
+ }
388
+ }
389
+ }
390
+ }
391
+ });
392
+ });
393
+ });
394
+ describe(" 2. Parser Class", () => {
395
+ test(" 1. Parse simple expression", () => {
396
+ let result = CreateASTFromString(Versions.v1_0_0, "value", "test");
397
+ expect(result).not.toBeUndefined();
398
+ expect(result.type, "First node should be file").toBe(NodeType.FILE);
399
+ expect(result.values.lines).not.toBeUndefined();
400
+ expect(result.values.lines, "File node should have 1 line").toHaveLength(1);
401
+ let expressionNode = result.values.lines[0];
402
+ expect(expressionNode.type, "Second node should be expression").toBe(NodeType.EXPRESSION);
403
+ expect(expressionNode.values.expression).not.toBeUndefined();
404
+ let identifierNode = expressionNode.values.expression;
405
+ expect(identifierNode.type, "Third node should be identifier token").toBe(TokenType.IDENTIFIER);
406
+ expect(identifierNode.data, "Identifier token's data should be 'value'").toBe("value");
407
+ });
408
+ test(" 2. Parse multipart expression", () => {
409
+ let result = CreateASTFromString(Versions.v1_0_0, "value.second", "test");
410
+ expect(result).not.toBeUndefined();
411
+ expect(result.type, "First node should be file").toBe(NodeType.FILE);
412
+ expect(result.values.lines).not.toBeUndefined();
413
+ expect(result.values.lines, "File node should have 1 line").toHaveLength(1);
414
+ let expressionNode = result.values.lines[0];
415
+ expect(expressionNode.type, "Second node should be expression").toBe(NodeType.EXPRESSION);
416
+ expect(expressionNode.values.expression).not.toBeUndefined();
417
+ let memberAccessNode = expressionNode.values.expression;
418
+ expect(memberAccessNode.type, "Third node should be member access node").toBe(NodeType.MEMBER_ACCESS);
419
+ expect(memberAccessNode.values.context.type, "Context should be identifier token").toBe(TokenType.IDENTIFIER);
420
+ expect(memberAccessNode.values.context.data, "Identifier token's data should be 'value'").toBe("value");
421
+ expect(memberAccessNode.values.memberName.type, "MemberName should be identifier token").toBe(TokenType.IDENTIFIER);
422
+ expect(memberAccessNode.values.memberName.data, "MemberName token's data should be 'second'").toBe("second");
423
+ });
424
+ test(" 3. Parse multipart multipart expression", () => {
425
+ let result = CreateASTFromString(Versions.v1_0_0, "value.second.third", "test");
426
+ expect(result).not.toBeUndefined();
427
+ expect(result.type, "First node should be file").toBe(NodeType.FILE);
428
+ expect(result.values.lines).not.toBeUndefined();
429
+ expect(result.values.lines, "File node should have 1 line").toHaveLength(1);
430
+ let expressionNode = result.values.lines[0];
431
+ expect(expressionNode.type, "Second node should be expression").toBe(NodeType.EXPRESSION);
432
+ expect(expressionNode.values.expression).not.toBeUndefined();
433
+ let memberAccessNode = expressionNode.values.expression;
434
+ expect(memberAccessNode.type, "Third node should be member access node").toBe(NodeType.MEMBER_ACCESS);
435
+ expect(memberAccessNode.values.context.type, "Context should be identifier token").toBe(TokenType.IDENTIFIER);
436
+ expect(memberAccessNode.values.context.data, "Identifier token's data should be 'value'").toBe("value");
437
+ let memberAccessNode2 = memberAccessNode.values.memberName;
438
+ expect(memberAccessNode2.type, "MemberName should be member access node").toBe(NodeType.MEMBER_ACCESS);
439
+ expect(memberAccessNode2.values.context.type, "Context2 should be identifier token").toBe(TokenType.IDENTIFIER);
440
+ expect(memberAccessNode2.values.context.data, "Identifier token's data should be 'second'").toBe("second");
441
+ expect(memberAccessNode2.values.memberName.type, "MemberName should be identifier token").toBe(TokenType.IDENTIFIER);
442
+ expect(memberAccessNode2.values.memberName.data, "MemberName token's data should be 'second'").toBe("third");
443
+ });
444
+ test(" 4. Parse cast expression", () => {
445
+ let result = CreateASTFromString(Versions.v1_0_0, "value:cast", "test");
446
+ expect(result).not.toBeUndefined();
447
+ expect(result.type, "First node should be file").toBe(NodeType.FILE);
448
+ expect(result.values.lines).not.toBeUndefined();
449
+ expect(result.values.lines, "File node should have 1 line").toHaveLength(1);
450
+ let expressionNode = result.values.lines[0];
451
+ expect(expressionNode.type, "Second node should be expression").toBe(NodeType.EXPRESSION);
452
+ expect(expressionNode.values.expression).not.toBeUndefined();
453
+ let castNode = expressionNode.values.expression;
454
+ expect(castNode.type, "Third node should be cast node").toBe(NodeType.CAST);
455
+ let identifierNode = castNode.values.expression;
456
+ expect(identifierNode.type, "Third node's left hand should be identifier token").toBe(TokenType.IDENTIFIER);
457
+ expect(identifierNode.data, "Identifier token's data should be 'value'").toBe("value");
458
+ let identifierNode2 = castNode.values.castType;
459
+ expect(identifierNode2.type, "Third node's right hand should be identifier token").toBe(TokenType.IDENTIFIER);
460
+ expect(identifierNode2.data, "Identifier token's data should be 'value'").toBe("cast");
461
+ });
462
+ test(" 5. Parse multipart cast expression", () => {
463
+ let result = CreateASTFromString(Versions.v1_0_0, "value.second:cast", "test");
464
+ expect(result).not.toBeUndefined();
465
+ expect(result.type, "First node should be file").toBe(NodeType.FILE);
466
+ expect(result.values.lines).not.toBeUndefined();
467
+ expect(result.values.lines, "File node should have 1 line").toHaveLength(1);
468
+ let expressionNode = result.values.lines[0];
469
+ expect(expressionNode.type, "Second node should be expression").toBe(NodeType.EXPRESSION);
470
+ expect(expressionNode.values.expression).not.toBeUndefined();
471
+ let memberAccessNode = expressionNode.values.expression;
472
+ expect(memberAccessNode.type, "Third node should be member access node").toBe(NodeType.MEMBER_ACCESS);
473
+ expect(memberAccessNode.values.context.type, "Context should be identifier token").toBe(TokenType.IDENTIFIER);
474
+ expect(memberAccessNode.values.context.data, "Identifier token's data should be 'value'").toBe("value");
475
+ expect(memberAccessNode.values.memberName.type, "MemberName should be cast node").toBe(NodeType.CAST);
476
+ let castNode = memberAccessNode.values.memberName;
477
+ expect(castNode.type, "Fourth node should be cast node").toBe(NodeType.CAST);
478
+ expect(castNode.values.expression.type, "Cast node token's lhs should be a token").toBe(TokenType.IDENTIFIER);
479
+ expect(castNode.values.expression.data, "Cast node token's lhs should be 'second'").toBe("second");
480
+ let identifierNode2 = castNode.values.castType;
481
+ expect(identifierNode2.type, "Third node's right hand should be identifier token").toBe(TokenType.IDENTIFIER);
482
+ expect(identifierNode2.data, "Identifier token's data should be 'value'").toBe("cast");
483
+ });
484
+ test(" 6. Parse multipart double cast expression", () => {
485
+ let result = CreateASTFromString(Versions.v1_0_0, "value.second:cast.third:cast2", "test");
486
+ expect(result).not.toBeUndefined();
487
+ expect(result.type, "First node should be file").toBe(NodeType.FILE);
488
+ expect(result.values.lines).not.toBeUndefined();
489
+ expect(result.values.lines, "File node should have 1 line").toHaveLength(1);
490
+ let expressionNode = result.values.lines[0];
491
+ expect(expressionNode.type, "Second node should be expression").toBe(NodeType.EXPRESSION);
492
+ expect(expressionNode.values.expression).not.toBeUndefined();
493
+ let valueDOTsecond = expressionNode.values.expression;
494
+ expect(valueDOTsecond.type, "Third node should be member access node").toBe(NodeType.MEMBER_ACCESS);
495
+ expect(valueDOTsecond.values.context.type, "Context should be identifier token").toBe(TokenType.IDENTIFIER);
496
+ expect(valueDOTsecond.values.context.data, "Identifier token's data should be 'value'").toBe("value");
497
+ expect(valueDOTsecond.values.memberName.type, "MemberName should be cast node").toBe(NodeType.MEMBER_ACCESS);
498
+ let secondDOTthird = valueDOTsecond.values.memberName;
499
+ expect(secondDOTthird.type, "Fourth node should be member access node").toBe(NodeType.MEMBER_ACCESS);
500
+ expect(secondDOTthird.values.context.type, "Context should be cast token").toBe(NodeType.CAST);
501
+ let secondCOLONcast = secondDOTthird.values.context;
502
+ expect(secondCOLONcast.type, "Fourth node lhs should be cast node").toBe(NodeType.CAST);
503
+ expect(secondCOLONcast.values.expression.type, "Cast node token's lhs should be a token").toBe(TokenType.IDENTIFIER);
504
+ expect(secondCOLONcast.values.expression.data, "Cast node token's lhs should be 'second'").toBe("second");
505
+ let cast = secondCOLONcast.values.castType;
506
+ expect(cast.type, "Fourth node's cast's rhs should be identifier token").toBe(TokenType.IDENTIFIER);
507
+ expect(cast.data, "Identifier token's data should be 'value'").toBe("cast");
508
+ let thirdCOLONcast2 = secondDOTthird.values.memberName;
509
+ expect(thirdCOLONcast2.type, "Fourth node lhs should be cast node").toBe(NodeType.CAST);
510
+ expect(thirdCOLONcast2.values.expression.type, "Cast node token's lhs should be a token").toBe(TokenType.IDENTIFIER);
511
+ expect(thirdCOLONcast2.values.expression.data, "Cast node token's lhs should be 'third'").toBe("third");
512
+ let cast2 = thirdCOLONcast2.values.castType;
513
+ expect(cast2.type, "Fourth node's cast's rhs should be identifier token").toBe(TokenType.IDENTIFIER);
514
+ expect(cast2.data, "Identifier token's data should be 'value'").toBe("cast2");
515
+ });
516
+ });
@@ -0,0 +1,68 @@
1
+ import { describe, expect, test } from "vitest";
2
+ import { TokenizeExpression, TokenType } from "../Tokenizer.js";
3
+ import { Versions } from "../../../Constants/Versions.js";
4
+ describe("Tokenizer", () => {
5
+ let version = Versions.v1_0_0;
6
+ test(" 1. Tokenize simple expression", () => {
7
+ let result = TokenizeExpression("value", version);
8
+ expect(result).toHaveLength(1);
9
+ expect(result[0].type).toBe(TokenType.IDENTIFIER);
10
+ });
11
+ test(" 2. Tokenize multipart expression", () => {
12
+ let result = TokenizeExpression("value.second", version);
13
+ expect(result).toHaveLength(3);
14
+ expect(result).toContainAtLeast([{ type: TokenType.IDENTIFIER }, { type: TokenType.OPERATOR }, { type: TokenType.IDENTIFIER }]);
15
+ });
16
+ test(" 3. Tokenize function", () => {
17
+ let result = TokenizeExpression("value()", version);
18
+ expect(result).toHaveLength(3);
19
+ expect(result).toContainAtLeast([{ type: TokenType.IDENTIFIER }, { type: TokenType.OPERATOR }, { type: TokenType.OPERATOR }]);
20
+ });
21
+ test(" 4. Tokenize function with parameters", () => {
22
+ let result = TokenizeExpression("value(first, second)", version);
23
+ expect(result).toHaveLength(7);
24
+ expect(result).toContainAtLeast([
25
+ { type: TokenType.IDENTIFIER },
26
+ { type: TokenType.OPERATOR },
27
+ { type: TokenType.IDENTIFIER },
28
+ { type: TokenType.WHITESPACE },
29
+ { type: TokenType.OPERATOR },
30
+ { type: TokenType.IDENTIFIER },
31
+ { type: TokenType.OPERATOR },
32
+ ]);
33
+ });
34
+ test(" 5. Tokenize cast", () => {
35
+ let result = TokenizeExpression("value:=number", version);
36
+ expect(result).toHaveLength(4);
37
+ expect(result).toContainAtLeast([
38
+ { type: TokenType.IDENTIFIER },
39
+ { type: TokenType.OPERATOR },
40
+ { type: TokenType.OPERATOR },
41
+ { type: TokenType.IDENTIFIER },
42
+ ]);
43
+ });
44
+ test(" 6. Tokenize cast multipart", () => {
45
+ let result = TokenizeExpression("value:=number.second", version);
46
+ expect(result).toHaveLength(6);
47
+ expect(result).toContainAtLeast([
48
+ { type: TokenType.IDENTIFIER },
49
+ { type: TokenType.OPERATOR },
50
+ { type: TokenType.OPERATOR },
51
+ { type: TokenType.IDENTIFIER },
52
+ { type: TokenType.OPERATOR },
53
+ { type: TokenType.IDENTIFIER },
54
+ ]);
55
+ });
56
+ test(" 7. Tokenize multipart cast", () => {
57
+ let result = TokenizeExpression("value.second:=number", version);
58
+ expect(result).toHaveLength(6);
59
+ expect(result).toContainAtLeast([
60
+ { type: TokenType.IDENTIFIER },
61
+ { type: TokenType.OPERATOR },
62
+ { type: TokenType.IDENTIFIER },
63
+ { type: TokenType.OPERATOR },
64
+ { type: TokenType.OPERATOR },
65
+ { type: TokenType.IDENTIFIER },
66
+ ]);
67
+ });
68
+ });
@@ -0,0 +1,4 @@
1
+ import { EvaluationChain } from "./EvaluatorChain.js";
2
+ import { EvaluationString } from "./EvaluatorString.js";
3
+ import { ExpressionConfiguration } from "./EvaluatorSteps.js";
4
+ export declare function CreateExpression(rawText: string, sourceFile: string, config: Required<ExpressionConfiguration>): EvaluationString | EvaluationChain;
@@ -0,0 +1,85 @@
1
+ import { CreateASTFromString } from "./Compiler/Parser.js";
2
+ import { OrderASTSequentially, OrderedNodeSequencesToTrees } from "./Traverser.js";
3
+ import { EvaluationString } from "./EvaluatorString.js";
4
+ import { ExpressionType, matchExpression } from "./EvaluatorSteps.js";
5
+ import { ExpressionSyntaxError } from "../Constants/Errors.js";
6
+ const expressionCache = new Map();
7
+ function CompareConfigs(a, b) {
8
+ if (a.startType === b.startType &&
9
+ a.outputTypes.length === b.outputTypes.length &&
10
+ a.duringLoad === b.duringLoad &&
11
+ a.version === b.version &&
12
+ a.cacheable === b.cacheable) {
13
+ for (let i = 0; i < a.outputTypes.length; i++) {
14
+ if (a.outputTypes[i] !== b.outputTypes[i])
15
+ return false;
16
+ }
17
+ return true;
18
+ }
19
+ return false;
20
+ }
21
+ export function CreateExpression(rawText, sourceFile, config) {
22
+ if (rawText.includes("${")) {
23
+ console.warn(`Expression contains deprecated syntax, use @ instead of $: ${rawText}`);
24
+ }
25
+ const cached = expressionCache.get(rawText);
26
+ if (cached) {
27
+ for (let entry of cached) {
28
+ if (CompareConfigs(entry.config, config)) {
29
+ return entry.expression;
30
+ }
31
+ }
32
+ }
33
+ let sources = [];
34
+ let expressions = [];
35
+ let type;
36
+ let i = 0;
37
+ let prepared_text = rawText
38
+ .replace(matchExpression, (match, index) => {
39
+ let ast = CreateASTFromString(config.version, match.slice(2, -1), sourceFile);
40
+ if (!ast)
41
+ throw new ExpressionSyntaxError(`Failed to parse expression: ${rawText}`, {
42
+ file: sourceFile,
43
+ text: rawText,
44
+ line: 0
45
+ }, index);
46
+ sources.push(ast);
47
+ let orderedAST = OrderASTSequentially(ast);
48
+ expressions.push({
49
+ //result is one per line but we only have one line.
50
+ expression: OrderedNodeSequencesToTrees(orderedAST, config)[0],
51
+ offset: index
52
+ });
53
+ expressions[expressions.length - 1].expression.rawText = rawText;
54
+ return "@{" + i++ + "}";
55
+ })
56
+ .trim();
57
+ let finalExpression;
58
+ if (prepared_text === "@{0}") {
59
+ finalExpression = expressions[0].expression;
60
+ if (config.outputArray || config.outputMap) {
61
+ finalExpression.type = ExpressionType.Collection;
62
+ }
63
+ else if (config.outputTypes[0] === "Function" || config.outputTypes[0] === Function) {
64
+ finalExpression.type = ExpressionType.Function;
65
+ }
66
+ else {
67
+ finalExpression.type = ExpressionType.Value;
68
+ }
69
+ }
70
+ else {
71
+ finalExpression = new EvaluationString(rawText, prepared_text, expressions, config);
72
+ }
73
+ //Non-string output types may only have one expression within.
74
+ if ((config.outputTypes.length !== 1 || (config.outputTypes[0] !== "String" && config.outputTypes[0] !== String))
75
+ && prepared_text != "@{0}") {
76
+ throw new Error(`Expressions returning non-string results must not contain non-expression syntax.`);
77
+ }
78
+ if (!cached) {
79
+ expressionCache.set(rawText, [{ expression: finalExpression, config }]);
80
+ }
81
+ else {
82
+ cached.push({ expression: finalExpression, config });
83
+ }
84
+ return finalExpression;
85
+ }