@matter/model 0.12.0-alpha.0-20241228-9f74a0273 → 0.12.0-alpha.0-20241231-14ac774ba

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 (73) hide show
  1. package/dist/cjs/aspects/Constraint.d.ts +24 -15
  2. package/dist/cjs/aspects/Constraint.d.ts.map +1 -1
  3. package/dist/cjs/aspects/Constraint.js +268 -198
  4. package/dist/cjs/aspects/Constraint.js.map +2 -2
  5. package/dist/cjs/common/FieldValue.d.ts +10 -4
  6. package/dist/cjs/common/FieldValue.d.ts.map +1 -1
  7. package/dist/cjs/common/FieldValue.js +1 -1
  8. package/dist/cjs/common/FieldValue.js.map +1 -1
  9. package/dist/cjs/common/Metatype.d.ts +19 -1
  10. package/dist/cjs/common/Metatype.d.ts.map +1 -1
  11. package/dist/cjs/common/Metatype.js +171 -170
  12. package/dist/cjs/common/Metatype.js.map +1 -1
  13. package/dist/cjs/common/Specification.d.ts +1 -1
  14. package/dist/cjs/common/Specification.d.ts.map +1 -1
  15. package/dist/cjs/logic/ModelDiff.d.ts +40 -0
  16. package/dist/cjs/logic/ModelDiff.d.ts.map +1 -0
  17. package/dist/cjs/logic/ModelDiff.js +119 -0
  18. package/dist/cjs/logic/ModelDiff.js.map +6 -0
  19. package/dist/cjs/logic/definition-validation/ValueValidator.js +1 -1
  20. package/dist/cjs/logic/definition-validation/ValueValidator.js.map +1 -1
  21. package/dist/cjs/logic/index.d.ts +1 -0
  22. package/dist/cjs/logic/index.d.ts.map +1 -1
  23. package/dist/cjs/logic/index.js +1 -0
  24. package/dist/cjs/logic/index.js.map +1 -1
  25. package/dist/cjs/parser/Lexer.d.ts +3 -3
  26. package/dist/cjs/parser/Lexer.d.ts.map +1 -1
  27. package/dist/cjs/parser/Lexer.js +35 -31
  28. package/dist/cjs/parser/Lexer.js.map +1 -1
  29. package/dist/cjs/parser/Token.d.ts +5 -2
  30. package/dist/cjs/parser/Token.d.ts.map +1 -1
  31. package/dist/cjs/parser/TokenStream.js +2 -2
  32. package/dist/esm/aspects/Constraint.d.ts +24 -15
  33. package/dist/esm/aspects/Constraint.d.ts.map +1 -1
  34. package/dist/esm/aspects/Constraint.js +269 -199
  35. package/dist/esm/aspects/Constraint.js.map +2 -2
  36. package/dist/esm/common/FieldValue.d.ts +10 -4
  37. package/dist/esm/common/FieldValue.d.ts.map +1 -1
  38. package/dist/esm/common/FieldValue.js +1 -1
  39. package/dist/esm/common/FieldValue.js.map +1 -1
  40. package/dist/esm/common/Metatype.d.ts +19 -1
  41. package/dist/esm/common/Metatype.d.ts.map +1 -1
  42. package/dist/esm/common/Metatype.js +171 -170
  43. package/dist/esm/common/Metatype.js.map +1 -1
  44. package/dist/esm/common/Specification.d.ts +1 -1
  45. package/dist/esm/common/Specification.d.ts.map +1 -1
  46. package/dist/esm/logic/ModelDiff.d.ts +40 -0
  47. package/dist/esm/logic/ModelDiff.d.ts.map +1 -0
  48. package/dist/esm/logic/ModelDiff.js +99 -0
  49. package/dist/esm/logic/ModelDiff.js.map +6 -0
  50. package/dist/esm/logic/definition-validation/ValueValidator.js +1 -1
  51. package/dist/esm/logic/definition-validation/ValueValidator.js.map +1 -1
  52. package/dist/esm/logic/index.d.ts +1 -0
  53. package/dist/esm/logic/index.d.ts.map +1 -1
  54. package/dist/esm/logic/index.js +1 -0
  55. package/dist/esm/logic/index.js.map +1 -1
  56. package/dist/esm/parser/Lexer.d.ts +3 -3
  57. package/dist/esm/parser/Lexer.d.ts.map +1 -1
  58. package/dist/esm/parser/Lexer.js +35 -31
  59. package/dist/esm/parser/Lexer.js.map +1 -1
  60. package/dist/esm/parser/Token.d.ts +5 -2
  61. package/dist/esm/parser/Token.d.ts.map +1 -1
  62. package/dist/esm/parser/TokenStream.js +2 -2
  63. package/package.json +4 -4
  64. package/src/aspects/Constraint.ts +340 -215
  65. package/src/common/FieldValue.ts +10 -5
  66. package/src/common/Metatype.ts +200 -181
  67. package/src/common/Specification.ts +1 -1
  68. package/src/logic/ModelDiff.ts +150 -0
  69. package/src/logic/definition-validation/ValueValidator.ts +1 -1
  70. package/src/logic/index.ts +1 -0
  71. package/src/parser/Lexer.ts +38 -40
  72. package/src/parser/Token.ts +11 -1
  73. package/src/parser/TokenStream.ts +2 -2
@@ -9,17 +9,15 @@ import { Aspect } from "./Aspect.js";
9
9
  * An operational view of constraints as defined by the Matter specification.
10
10
  *
11
11
  * A "constraint" limits possible data values.
12
- *
13
- * Formally a constraint is not considered a quality by the specification. It is handled similarly to qualities, though,
14
- * so we keep it in the same section.
15
12
  */
16
13
  export declare class Constraint extends Aspect<Constraint.Definition> implements Constraint.Ast {
17
14
  desc?: boolean;
18
- value?: FieldValue;
19
- min?: FieldValue;
20
- max?: FieldValue;
15
+ value?: Constraint.Expression;
16
+ min?: Constraint.Expression;
17
+ max?: Constraint.Expression;
21
18
  in?: FieldValue;
22
19
  entry?: Constraint;
20
+ cpMax?: number;
23
21
  parts?: Constraint[];
24
22
  /**
25
23
  * Initialize from a Constraint.Definition or the constraint DSL defined by the Matter Specification.
@@ -35,7 +33,7 @@ export declare class Constraint extends Aspect<Constraint.Definition> implements
35
33
  export declare namespace Constraint {
36
34
  type NumberOrIdentifier = number | string;
37
35
  /**
38
- * Parsed list structure.
36
+ * Parsed constraint.
39
37
  */
40
38
  type Ast = {
41
39
  /**
@@ -45,15 +43,15 @@ export declare namespace Constraint {
45
43
  /**
46
44
  * Constant value.
47
45
  */
48
- value?: FieldValue;
46
+ value?: Expression;
49
47
  /**
50
48
  * Lower bound on value or sequence length.
51
49
  */
52
- min?: FieldValue;
50
+ min?: Expression;
53
51
  /**
54
52
  * Upper bound on value or sequence length.
55
53
  */
56
- max?: FieldValue;
54
+ max?: Expression;
57
55
  /**
58
56
  * Require set membership for the value.
59
57
  */
@@ -62,21 +60,32 @@ export declare namespace Constraint {
62
60
  * Constraint on list child element.
63
61
  */
64
62
  entry?: Ast;
63
+ /**
64
+ * Constraint on codepoints in a string.
65
+ */
66
+ cpMax?: number;
65
67
  /**
66
68
  * List of sub-constraints in a sequence.
67
69
  */
68
70
  parts?: Ast[];
69
71
  };
72
+ /**
73
+ * Parsed binary operator.
74
+ */
75
+ interface BinaryOperator {
76
+ type: "+" | "-";
77
+ lhs: Expression;
78
+ rhs: Expression;
79
+ }
80
+ /**
81
+ * Parsed expression.
82
+ */
83
+ type Expression = FieldValue | BinaryOperator;
70
84
  /**
71
85
  * These are all ways to describe a constraint.
72
86
  */
73
87
  type Definition = (Ast & {
74
88
  definition?: Definition;
75
89
  }) | string | number | undefined;
76
- /**
77
- * Parse constraint DSL. Extremely lenient.
78
- */
79
- function parse(constraint: Constraint, definition: string): Ast;
80
- function serialize(ast: Ast): string;
81
90
  }
82
91
  //# sourceMappingURL=Constraint.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Constraint.d.ts","sourceRoot":"","sources":["../../../src/aspects/Constraint.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC;;;;;;;GAOG;AACH,qBAAa,UAAW,SAAQ,MAAM,CAAC,UAAU,CAAC,UAAU,CAAE,YAAW,UAAU,CAAC,GAAG;IAC3E,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,GAAG,CAAC,EAAE,UAAU,CAAC;IACjB,GAAG,CAAC,EAAE,UAAU,CAAC;IACjB,EAAE,CAAC,EAAE,UAAU,CAAC;IAChB,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,KAAK,CAAC,EAAE,UAAU,EAAE,CAAC;IAE7B;;OAEG;gBACS,UAAU,EAAE,UAAU,CAAC,UAAU;IAwD7C;;OAEG;IACH,IAAI,CAAC,KAAK,EAAE,UAAU,EAAE,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,OAAO;IA0DzD,QAAQ;cAOE,MAAM;CAM5B;AAED,yBAAiB,UAAU,CAAC;IACxB,KAAY,kBAAkB,GAAG,MAAM,GAAG,MAAM,CAAC;IAEjD;;OAEG;IACH,KAAY,GAAG,GAAG;QACd;;WAEG;QACH,IAAI,CAAC,EAAE,OAAO,CAAC;QAEf;;WAEG;QACH,KAAK,CAAC,EAAE,UAAU,CAAC;QAEnB;;WAEG;QACH,GAAG,CAAC,EAAE,UAAU,CAAC;QAEjB;;WAEG;QACH,GAAG,CAAC,EAAE,UAAU,CAAC;QAEjB;;WAEG;QACH,EAAE,CAAC,EAAE,UAAU,CAAC;QAEhB;;WAEG;QACH,KAAK,CAAC,EAAE,GAAG,CAAC;QAEZ;;WAEG;QACH,KAAK,CAAC,EAAE,GAAG,EAAE,CAAC;KACjB,CAAC;IAEF;;OAEG;IACH,KAAY,UAAU,GAAG,CAAC,GAAG,GAAG;QAAE,UAAU,CAAC,EAAE,UAAU,CAAA;KAAE,CAAC,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;IA8G3F;;OAEG;IACH,SAAgB,KAAK,CAAC,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,GAAG,GAAG,CAwGrE;IA6BD,SAAgB,SAAS,CAAC,GAAG,EAAE,GAAG,GAAG,MAAM,CAQ1C;CACJ"}
1
+ {"version":3,"file":"Constraint.d.ts","sourceRoot":"","sources":["../../../src/aspects/Constraint.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC;;;;GAIG;AACH,qBAAa,UAAW,SAAQ,MAAM,CAAC,UAAU,CAAC,UAAU,CAAE,YAAW,UAAU,CAAC,GAAG;IAC3E,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,UAAU,CAAC,UAAU,CAAC;IAC9B,GAAG,CAAC,EAAE,UAAU,CAAC,UAAU,CAAC;IAC5B,GAAG,CAAC,EAAE,UAAU,CAAC,UAAU,CAAC;IAC5B,EAAE,CAAC,EAAE,UAAU,CAAC;IAChB,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,UAAU,EAAE,CAAC;IAE7B;;OAEG;gBACS,UAAU,EAAE,UAAU,CAAC,UAAU;IA2D7C;;OAEG;IACH,IAAI,CAAC,KAAK,EAAE,UAAU,EAAE,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,OAAO;IAoFzD,QAAQ;cAOE,MAAM;CAM5B;AAED,yBAAiB,UAAU,CAAC;IACxB,KAAY,kBAAkB,GAAG,MAAM,GAAG,MAAM,CAAC;IAEjD;;OAEG;IACH,KAAY,GAAG,GAAG;QACd;;WAEG;QACH,IAAI,CAAC,EAAE,OAAO,CAAC;QAEf;;WAEG;QACH,KAAK,CAAC,EAAE,UAAU,CAAC;QAEnB;;WAEG;QACH,GAAG,CAAC,EAAE,UAAU,CAAC;QAEjB;;WAEG;QACH,GAAG,CAAC,EAAE,UAAU,CAAC;QAEjB;;WAEG;QACH,EAAE,CAAC,EAAE,UAAU,CAAC;QAEhB;;WAEG;QACH,KAAK,CAAC,EAAE,GAAG,CAAC;QAEZ;;WAEG;QACH,KAAK,CAAC,EAAE,MAAM,CAAC;QAEf;;WAEG;QACH,KAAK,CAAC,EAAE,GAAG,EAAE,CAAC;KACjB,CAAC;IAEF;;OAEG;IACH,UAAiB,cAAc;QAC3B,IAAI,EAAE,GAAG,GAAG,GAAG,CAAC;QAEhB,GAAG,EAAE,UAAU,CAAC;QAEhB,GAAG,EAAE,UAAU,CAAC;KACnB;IAED;;OAEG;IACH,KAAY,UAAU,GAAG,UAAU,GAAG,cAAc,CAAC;IAErD;;OAEG;IACH,KAAY,UAAU,GAAG,CAAC,GAAG,GAAG;QAAE,UAAU,CAAC,EAAE,UAAU,CAAA;KAAE,CAAC,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;CAC9F"}
@@ -21,6 +21,8 @@ __export(Constraint_exports, {
21
21
  Constraint: () => Constraint
22
22
  });
23
23
  module.exports = __toCommonJS(Constraint_exports);
24
+ var import_Lexer = require("#parser/Lexer.js");
25
+ var import_TokenStream = require("#parser/TokenStream.js");
24
26
  var import_general = require("@matter/general");
25
27
  var import_common = require("../common/index.js");
26
28
  var import_Aspect = require("./Aspect.js");
@@ -41,7 +43,7 @@ class Constraint extends import_Aspect.Aspect {
41
43
  if (definition.match(/(?:0b[0x ]*x[0x ]*)|(?:0x[0x_]*x[0x_]*)|(?:00[0x]*x)/i)) {
42
44
  break;
43
45
  }
44
- ast = Constraint.parse(this, definition);
46
+ ast = Parser.parse(this, definition);
45
47
  break;
46
48
  case "number":
47
49
  ast = { value: definition };
@@ -74,6 +76,9 @@ class Constraint extends import_Aspect.Aspect {
74
76
  if (ast.entry !== void 0) {
75
77
  this.entry = new Constraint(ast.entry);
76
78
  }
79
+ if (ast.cpMax !== void 0) {
80
+ this.cpMax = ast.cpMax;
81
+ }
77
82
  if (ast.parts !== void 0) {
78
83
  this.parts = ast.parts.map((p) => new Constraint(p));
79
84
  }
@@ -87,10 +92,34 @@ class Constraint extends import_Aspect.Aspect {
87
92
  if (!raw && (typeof value2 === "string" || Array.isArray(value2))) {
88
93
  return value2.length;
89
94
  }
90
- if ((0, import_general.isObject)(value2)) {
91
- const { type, name } = value2;
92
- if (type === import_common.FieldValue.reference && typeof name === "string") {
93
- value2 = valueOf(properties?.[(0, import_general.camelize)(name)], raw);
95
+ if (typeof value2 === "object" && value2 !== null && "type" in value2) {
96
+ const { type } = value2;
97
+ switch (type) {
98
+ case import_common.FieldValue.reference:
99
+ if (typeof value2.name === "string") {
100
+ value2 = valueOf(properties?.[(0, import_general.camelize)(value2.name)], raw);
101
+ }
102
+ break;
103
+ case "+":
104
+ {
105
+ const lhs = valueOf(value2.lhs);
106
+ const rhs = valueOf(value2.rhs);
107
+ if (typeof lhs === "number" && typeof rhs === "number") {
108
+ return lhs + rhs;
109
+ }
110
+ return void 0;
111
+ }
112
+ break;
113
+ case "-":
114
+ {
115
+ const lhs = valueOf(value2.lhs);
116
+ const rhs = valueOf(value2.rhs);
117
+ if (typeof lhs === "number" && typeof rhs === "number") {
118
+ return lhs - rhs;
119
+ }
120
+ return void 0;
121
+ }
122
+ break;
94
123
  }
95
124
  }
96
125
  return value2;
@@ -101,7 +130,7 @@ class Constraint extends import_Aspect.Aspect {
101
130
  if (this.in) {
102
131
  let set = valueOf(this.in, true);
103
132
  if (!Array.isArray(set)) {
104
- set = [set];
133
+ set = set === void 0 ? [] : [set];
105
134
  }
106
135
  return set.indexOf(value) !== -1;
107
136
  }
@@ -133,7 +162,7 @@ class Constraint extends import_Aspect.Aspect {
133
162
  if (!this.valid && this.definition) {
134
163
  return this.definition.toString();
135
164
  }
136
- return Constraint.serialize(this);
165
+ return Serializer.serialize(this);
137
166
  }
138
167
  freeze() {
139
168
  if (this.parts) {
@@ -142,221 +171,262 @@ class Constraint extends import_Aspect.Aspect {
142
171
  super.freeze();
143
172
  }
144
173
  }
145
- ((Constraint2) => {
146
- function parseValue(numOrName) {
147
- let value;
148
- if (numOrName.match(/^-?0[xb]/)) {
149
- value = Number.parseInt(numOrName.replace(/[_ ]/g, ""));
150
- } else {
151
- value = Number.parseFloat(numOrName);
152
- }
153
- if (typeof numOrName === "string") {
154
- const lower = numOrName.toLowerCase();
155
- switch (lower) {
156
- case "true":
157
- return true;
158
- case "false":
159
- return false;
160
- }
161
- }
162
- if (Number.isNaN(value)) {
163
- return import_common.FieldValue.Reference((0, import_general.camelize)(numOrName));
174
+ var Serializer;
175
+ ((Serializer2) => {
176
+ function serialize(ast) {
177
+ if (ast.parts) {
178
+ return ast.parts.map(serialize).join(", ");
164
179
  }
165
- if (numOrName.endsWith("%")) {
166
- return import_common.FieldValue.Percent(value);
180
+ if (ast.entry) {
181
+ return `${serializeAtom(ast)}[${serialize(ast.entry)}]`;
167
182
  }
168
- if (numOrName.endsWith("\xB0C")) {
169
- return import_common.FieldValue.Celsius(value);
183
+ if (ast.cpMax) {
184
+ return `${serializeAtom(ast)}{${ast.cpMax}}`;
170
185
  }
171
- return value;
172
- }
173
- function parseAtom(constraint, words) {
174
- switch (words.length) {
175
- case 0:
176
- return void 0;
177
- case 1:
178
- switch (words[0].toLowerCase()) {
179
- case "desc":
180
- return { desc: true };
181
- case "all":
182
- case "any":
183
- return {};
184
- }
185
- const value = parseValue(words[0]);
186
- if (value === void 0 || value === null) {
187
- return;
188
- }
189
- return { value };
190
- case 2:
191
- switch (words[0].toLowerCase()) {
192
- case "min":
193
- const min = parseValue(words[1]);
194
- if (min === void 0 || min === null) {
195
- return;
196
- }
197
- return { min };
198
- case "max":
199
- const max = parseValue(words[1]);
200
- if (max === void 0 || max === null) {
201
- return;
202
- }
203
- return { max };
204
- case "in":
205
- const ref = parseValue(words[1]);
206
- return { in: ref };
207
- default:
208
- constraint.error(
209
- "INVALID_CONSTRAINT",
210
- `Two word constraint "${words.join(" ")}" does not start with "min" or "max"`
211
- );
212
- }
213
- return;
214
- case 3:
215
- if (words[1].toLowerCase() === "to") {
216
- let parseBound2 = function(name, pos) {
217
- if (words[pos].toLowerCase() === name) {
218
- return void 0;
219
- }
220
- return parseValue(words[pos]);
221
- };
222
- var parseBound = parseBound2;
223
- const ast = {};
224
- const min = parseBound2("min", 0);
225
- if (min !== void 0 && min !== null) {
226
- ast.min = min;
227
- }
228
- const max = parseBound2("max", 2);
229
- if (max !== void 0 && max !== null) {
230
- ast.max = max;
231
- }
232
- if (ast.min !== void 0 && ast.min !== null || ast.max !== void 0 && ast.max !== null) {
233
- return ast;
234
- }
235
- }
236
- return;
237
- }
238
- constraint.error("INVALID_CONSTRAINT", `Unrecognized value constraint "${words.join(" ")}"`);
186
+ return serializeAtom(ast);
239
187
  }
240
- function parse(constraint, definition) {
241
- let pos = 2;
242
- let current = definition[0];
243
- let peeked = definition[1];
244
- function next() {
245
- current = peeked;
246
- if (pos === definition.length) {
247
- peeked = void 0;
248
- } else {
249
- peeked = definition[pos];
250
- pos++;
251
- }
252
- }
253
- function scan(depth) {
254
- const parts = Array();
255
- let words = Array();
256
- let word = "";
257
- function parseWords() {
258
- if (word) {
259
- words.push(word);
260
- word = "";
188
+ Serializer2.serialize = serialize;
189
+ function serializeValue(value, inExpr = false) {
190
+ if (typeof value !== "object" || value === null || Array.isArray(value) || value instanceof Date) {
191
+ return import_common.FieldValue.serialize(value);
192
+ }
193
+ switch (value.type) {
194
+ case "+":
195
+ case "-":
196
+ const sum = `${serializeValue(value.lhs, true)} ${value.type} ${serializeValue(value.rhs, true)}`;
197
+ if (inExpr) {
198
+ return `(${sum})`;
261
199
  }
262
- const atom = parseAtom(constraint, words);
263
- words = Array();
264
- return atom;
265
- }
266
- function emit() {
267
- const atom = parseWords();
268
- if (atom !== void 0) {
269
- parts.push(atom);
270
- }
271
- }
272
- while (current !== void 0) {
273
- switch (current) {
274
- case " ":
275
- case " ":
276
- case "\r":
277
- case "\n":
278
- case "\v":
279
- case "\f":
280
- if (word) {
281
- words.push(word);
282
- word = "";
283
- }
284
- break;
285
- case "[":
286
- next();
287
- let ast = parseWords();
288
- const entry = scan(depth + 1);
289
- if (entry) {
290
- if (!ast) {
291
- ast = {};
292
- }
293
- ast.entry = entry;
294
- }
295
- if (ast) {
296
- parts.push(ast);
297
- }
298
- break;
299
- case "]":
300
- if (!depth) {
301
- constraint.error("INVALID_CONSTRAINT", 'Unexpected "]"');
302
- break;
303
- }
304
- emit();
305
- if (parts.length > 1) {
306
- return { parts };
307
- }
308
- return parts[0];
309
- case ",":
310
- emit();
311
- break;
312
- default:
313
- word += current;
314
- break;
315
- }
316
- next();
317
- }
318
- if (depth) {
319
- constraint.error("INVALID_CONSTRAINT", "Unterminated sub-constraint");
320
- }
321
- emit();
322
- if (parts.length < 2) {
323
- return parts[0];
324
- }
325
- return { parts };
200
+ return sum;
201
+ default:
202
+ return import_common.FieldValue.serialize(value);
326
203
  }
327
- return scan(0);
328
204
  }
329
- Constraint2.parse = parse;
330
205
  function serializeAtom(ast) {
331
206
  if (ast.desc) {
332
207
  return "desc";
333
208
  }
334
209
  if (ast.value !== void 0 && ast.value !== null) {
335
- return `${import_common.FieldValue.serialize(ast.value)}`;
210
+ return `${serializeValue(ast.value)}`;
336
211
  }
337
212
  if (ast.min !== void 0 && ast.min !== null) {
338
213
  if (ast.max === void 0 || ast.max === null) {
339
- return `min ${import_common.FieldValue.serialize(ast.min)}`;
214
+ return `min ${serializeValue(ast.min)}`;
340
215
  }
341
- return `${import_common.FieldValue.serialize(ast.min)} to ${import_common.FieldValue.serialize(ast.max)}`;
216
+ return `${serializeValue(ast.min)} to ${serializeValue(ast.max)}`;
342
217
  }
343
218
  if (ast.max !== void 0 && ast.max !== null) {
344
- return `max ${import_common.FieldValue.serialize(ast.max)}`;
219
+ return `max ${serializeValue(ast.max)}`;
345
220
  }
346
221
  if (ast.in !== void 0) {
347
- return `in ${import_common.FieldValue.serialize(ast.in)}`;
222
+ return `in ${serializeValue(ast.in)}`;
348
223
  }
349
224
  return "all";
350
225
  }
351
- function serialize(ast) {
352
- if (ast.parts) {
353
- return ast.parts.map(serialize).join(", ");
226
+ })(Serializer || (Serializer = {}));
227
+ var Parser;
228
+ ((Parser2) => {
229
+ const lexer = new import_Lexer.Lexer(["in", "min", "max", "to", "all", "desc", "true", "false"]);
230
+ function parse(constraint, definition) {
231
+ const tokens = (0, import_TokenStream.TokenStream)(lexer.lex(definition, (code, message) => constraint.error(code, message)));
232
+ const result = parseParts();
233
+ if (tokens.token && tokens.token?.type !== ",") {
234
+ constraint.error("UNEXPECTED_CONSTRAINT_TOKEN", `Unexpected ${tokens.description}`);
354
235
  }
355
- if (ast.entry) {
356
- return `${serializeAtom(ast)}[${serialize(ast.entry)}]`;
236
+ return result;
237
+ function parseParts() {
238
+ const parts = Array();
239
+ while (true) {
240
+ const part = parsePart();
241
+ if (part !== void 0) {
242
+ parts.push(part);
243
+ }
244
+ if (tokens.done) {
245
+ break;
246
+ }
247
+ if (tokens.token?.type !== ",") {
248
+ break;
249
+ }
250
+ tokens.next();
251
+ }
252
+ if (!parts.length) {
253
+ return {};
254
+ }
255
+ if (parts.length === 1) {
256
+ return parts[0];
257
+ }
258
+ return { parts };
259
+ }
260
+ function parsePart() {
261
+ const result2 = parsePartWithoutSubconstraint();
262
+ if (result2 === void 0) {
263
+ return result2;
264
+ }
265
+ switch (tokens.token?.type) {
266
+ case "[":
267
+ {
268
+ tokens.next();
269
+ const entry = parseParts();
270
+ if (tokens.token?.type !== "]") {
271
+ constraint.error("MISSING_ENTRY_END", 'Entry constraint does not end with "]"');
272
+ }
273
+ tokens.next();
274
+ if (entry !== void 0) {
275
+ result2.entry = entry;
276
+ }
277
+ }
278
+ break;
279
+ case "{":
280
+ {
281
+ tokens.next();
282
+ if (tokens.token?.type !== "value") {
283
+ constraint.error(
284
+ "MISSING_CODEPOINT_MAX",
285
+ "Codepoint constraint does not specify maximum codepoint length"
286
+ );
287
+ if (tokens.peeked?.type === "}") {
288
+ tokens.next();
289
+ }
290
+ } else {
291
+ result2.cpMax = import_common.FieldValue.numericValue(
292
+ tokens.token.value
293
+ );
294
+ tokens.next();
295
+ }
296
+ if (tokens.token?.type !== "}") {
297
+ constraint.error("MISSING_CODEPOINT_END", 'Codepoint constraint does not end with "}"');
298
+ }
299
+ tokens.next();
300
+ }
301
+ break;
302
+ }
303
+ return result2;
304
+ }
305
+ function parsePartWithoutSubconstraint() {
306
+ const { token } = tokens;
307
+ if (!token) {
308
+ return;
309
+ }
310
+ switch (token.type) {
311
+ case "desc":
312
+ tokens.next();
313
+ return { desc: true };
314
+ case "all":
315
+ tokens.next();
316
+ return {};
317
+ case "min":
318
+ case "max":
319
+ tokens.next();
320
+ return parseSingleBound(token.type);
321
+ case "in":
322
+ tokens.next();
323
+ if (tokens.token?.type === "word") {
324
+ const name = tokens.token.value;
325
+ tokens.next();
326
+ return { in: import_common.FieldValue.Reference(name) };
327
+ }
328
+ constraint.error("MISSING_IN_FIELD", 'Expected field name to follow "in"');
329
+ break;
330
+ }
331
+ const value = parseExpression();
332
+ if (value === void 0 || tokens.token?.type !== "to") {
333
+ return { value };
334
+ }
335
+ tokens.next();
336
+ const max = parseExpression();
337
+ if (max === void 0) {
338
+ constraint.error("MISSING_UPPER_BOUND", `"to" must be followed by upper boundary value`);
339
+ return;
340
+ }
341
+ return {
342
+ min: value,
343
+ max
344
+ };
345
+ }
346
+ function parseSingleBound(kind) {
347
+ const bound = parseExpression();
348
+ if (bound === void 0) {
349
+ constraint.error("MISSING_SINGLE_BOUND", `"${kind}" must be followed by boundary value`);
350
+ return;
351
+ }
352
+ return { [kind]: bound };
353
+ }
354
+ function parseExpression() {
355
+ const value = parseValueExpression();
356
+ if (value === void 0) {
357
+ return value;
358
+ }
359
+ switch (tokens.token?.type) {
360
+ case "+":
361
+ case "-":
362
+ const type = tokens.token.type;
363
+ tokens.next();
364
+ const rhs = parseValueExpression();
365
+ if (rhs === void 0) {
366
+ constraint.error("MISSING_RIGHT_OPERAND", `Missing operand after "${type}"`);
367
+ return;
368
+ }
369
+ return {
370
+ type,
371
+ lhs: value,
372
+ rhs
373
+ };
374
+ }
375
+ return value;
376
+ }
377
+ function parseValueExpression() {
378
+ const { token } = tokens;
379
+ if (token === void 0) {
380
+ return;
381
+ }
382
+ switch (token.type) {
383
+ case "value":
384
+ tokens.next();
385
+ return token.value;
386
+ case "true":
387
+ tokens.next();
388
+ return true;
389
+ case "false":
390
+ tokens.next();
391
+ return false;
392
+ case "word":
393
+ const ref = import_common.FieldValue.Reference((0, import_general.camelize)(token.value));
394
+ tokens.next();
395
+ return ref;
396
+ case "-":
397
+ case "+": {
398
+ tokens.next();
399
+ let number = tokens.token?.type === "value" ? tokens.token.value : void 0;
400
+ if (number !== void 0) {
401
+ tokens.next();
402
+ if (token.type === "-") {
403
+ if (typeof number === "number") {
404
+ number *= -1;
405
+ } else if (import_common.FieldValue.is(number, import_common.FieldValue.percent) || import_common.FieldValue.is(number, import_common.FieldValue.celsius)) {
406
+ number.value *= -1;
407
+ } else {
408
+ number = void 0;
409
+ }
410
+ }
411
+ }
412
+ if (number === void 0) {
413
+ constraint.error("MISSING_NUMBER", `Unary "${token.type}" not followed by numeric value`);
414
+ return;
415
+ }
416
+ return number;
417
+ }
418
+ case "(": {
419
+ tokens.next();
420
+ const result2 = parseExpression();
421
+ if (tokens.token?.type !== ")") {
422
+ constraint.error("MISSING_GROUP_END", 'Group does not end with ")"');
423
+ }
424
+ tokens.next();
425
+ return result2;
426
+ }
427
+ }
357
428
  }
358
- return serializeAtom(ast);
359
429
  }
360
- Constraint2.serialize = serialize;
361
- })(Constraint || (Constraint = {}));
430
+ Parser2.parse = parse;
431
+ })(Parser || (Parser = {}));
362
432
  //# sourceMappingURL=Constraint.js.map