context-mapper-mcp 1.0.0

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 (51) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +238 -0
  3. package/dist/generators/plantuml.d.ts +17 -0
  4. package/dist/generators/plantuml.d.ts.map +1 -0
  5. package/dist/generators/plantuml.js +244 -0
  6. package/dist/generators/plantuml.js.map +1 -0
  7. package/dist/index.d.ts +7 -0
  8. package/dist/index.d.ts.map +1 -0
  9. package/dist/index.js +897 -0
  10. package/dist/index.js.map +1 -0
  11. package/dist/model/parser.d.ts +51 -0
  12. package/dist/model/parser.d.ts.map +1 -0
  13. package/dist/model/parser.js +934 -0
  14. package/dist/model/parser.js.map +1 -0
  15. package/dist/model/types.d.ts +121 -0
  16. package/dist/model/types.d.ts.map +1 -0
  17. package/dist/model/types.js +12 -0
  18. package/dist/model/types.js.map +1 -0
  19. package/dist/model/validation.d.ts +36 -0
  20. package/dist/model/validation.d.ts.map +1 -0
  21. package/dist/model/validation.js +411 -0
  22. package/dist/model/validation.js.map +1 -0
  23. package/dist/model/writer.d.ts +30 -0
  24. package/dist/model/writer.d.ts.map +1 -0
  25. package/dist/model/writer.js +305 -0
  26. package/dist/model/writer.js.map +1 -0
  27. package/dist/tools/aggregate-tools.d.ts +295 -0
  28. package/dist/tools/aggregate-tools.d.ts.map +1 -0
  29. package/dist/tools/aggregate-tools.js +965 -0
  30. package/dist/tools/aggregate-tools.js.map +1 -0
  31. package/dist/tools/context-tools.d.ts +60 -0
  32. package/dist/tools/context-tools.d.ts.map +1 -0
  33. package/dist/tools/context-tools.js +166 -0
  34. package/dist/tools/context-tools.js.map +1 -0
  35. package/dist/tools/generation-tools.d.ts +29 -0
  36. package/dist/tools/generation-tools.d.ts.map +1 -0
  37. package/dist/tools/generation-tools.js +62 -0
  38. package/dist/tools/generation-tools.js.map +1 -0
  39. package/dist/tools/model-tools.d.ts +72 -0
  40. package/dist/tools/model-tools.d.ts.map +1 -0
  41. package/dist/tools/model-tools.js +186 -0
  42. package/dist/tools/model-tools.js.map +1 -0
  43. package/dist/tools/query-tools.d.ts +170 -0
  44. package/dist/tools/query-tools.d.ts.map +1 -0
  45. package/dist/tools/query-tools.js +322 -0
  46. package/dist/tools/query-tools.js.map +1 -0
  47. package/dist/tools/relationship-tools.d.ts +68 -0
  48. package/dist/tools/relationship-tools.d.ts.map +1 -0
  49. package/dist/tools/relationship-tools.js +178 -0
  50. package/dist/tools/relationship-tools.js.map +1 -0
  51. package/package.json +52 -0
@@ -0,0 +1,934 @@
1
+ /**
2
+ * CML Parser using Chevrotain
3
+ * Parses Context Mapper Language (CML) files into typed AST
4
+ */
5
+ import { createToken, Lexer, CstParser } from 'chevrotain';
6
+ import { v4 as uuidv4 } from 'uuid';
7
+ // ============================================
8
+ // LEXER TOKENS
9
+ // ============================================
10
+ // Whitespace and comments
11
+ const WhiteSpace = createToken({ name: 'WhiteSpace', pattern: /\s+/, group: Lexer.SKIPPED });
12
+ const LineComment = createToken({ name: 'LineComment', pattern: /\/\/[^\n\r]*/, group: Lexer.SKIPPED });
13
+ const BlockComment = createToken({ name: 'BlockComment', pattern: /\/\*[\s\S]*?\*\//, group: Lexer.SKIPPED });
14
+ // Identifier must be defined first for longer_alt references
15
+ const Identifier = createToken({ name: 'Identifier', pattern: /[a-zA-Z_][a-zA-Z0-9_]*/ });
16
+ // Keywords - use longer_alt so identifiers like "ServiceNowPlatform" aren't split
17
+ const ContextMap = createToken({ name: 'ContextMap', pattern: /ContextMap/, longer_alt: Identifier });
18
+ const BoundedContext = createToken({ name: 'BoundedContext', pattern: /BoundedContext/, longer_alt: Identifier });
19
+ const Aggregate = createToken({ name: 'Aggregate', pattern: /Aggregate/, longer_alt: Identifier });
20
+ const Entity = createToken({ name: 'Entity', pattern: /Entity/, longer_alt: Identifier });
21
+ const ValueObject = createToken({ name: 'ValueObject', pattern: /ValueObject/, longer_alt: Identifier });
22
+ const DomainEvent = createToken({ name: 'DomainEvent', pattern: /DomainEvent/, longer_alt: Identifier });
23
+ const Command = createToken({ name: 'Command', pattern: /Command/, longer_alt: Identifier });
24
+ const Service = createToken({ name: 'Service', pattern: /Service/, longer_alt: Identifier });
25
+ const Module = createToken({ name: 'Module', pattern: /Module/, longer_alt: Identifier });
26
+ // Relationship keywords
27
+ const Partnership = createToken({ name: 'Partnership', pattern: /Partnership/, longer_alt: Identifier });
28
+ const SharedKernel = createToken({ name: 'SharedKernel', pattern: /SharedKernel/, longer_alt: Identifier });
29
+ const CustomerSupplier = createToken({ name: 'CustomerSupplier', pattern: /Customer-Supplier/ });
30
+ // Relationship patterns
31
+ const UpstreamKw = createToken({ name: 'UpstreamKw', pattern: /[Uu]pstream/, longer_alt: Identifier });
32
+ const DownstreamKw = createToken({ name: 'DownstreamKw', pattern: /[Dd]ownstream/, longer_alt: Identifier });
33
+ const UpstreamShort = createToken({ name: 'UpstreamShort', pattern: /U(?![a-zA-Z0-9_])/ });
34
+ const DownstreamShort = createToken({ name: 'DownstreamShort', pattern: /D(?![a-zA-Z0-9_])/ });
35
+ const OHS = createToken({ name: 'OHS', pattern: /OHS/, longer_alt: Identifier });
36
+ const PL = createToken({ name: 'PL', pattern: /PL/, longer_alt: Identifier });
37
+ const ACL = createToken({ name: 'ACL', pattern: /ACL/, longer_alt: Identifier });
38
+ const CF = createToken({ name: 'CF', pattern: /CF/, longer_alt: Identifier });
39
+ // Property keywords
40
+ const Contains = createToken({ name: 'Contains', pattern: /contains/, longer_alt: Identifier });
41
+ const Implements = createToken({ name: 'Implements', pattern: /implements/, longer_alt: Identifier });
42
+ const Type = createToken({ name: 'Type', pattern: /type/, longer_alt: Identifier });
43
+ const State = createToken({ name: 'State', pattern: /state/, longer_alt: Identifier });
44
+ const DomainVisionStatement = createToken({ name: 'DomainVisionStatement', pattern: /domainVisionStatement/, longer_alt: Identifier });
45
+ const Responsibilities = createToken({ name: 'Responsibilities', pattern: /responsibilities/, longer_alt: Identifier });
46
+ const ImplementationTechnology = createToken({ name: 'ImplementationTechnology', pattern: /implementationTechnology/, longer_alt: Identifier });
47
+ const KnowledgeLevel = createToken({ name: 'KnowledgeLevel', pattern: /knowledgeLevel/, longer_alt: Identifier });
48
+ const AggregateRoot = createToken({ name: 'AggregateRoot', pattern: /aggregateRoot/, longer_alt: Identifier });
49
+ const Def = createToken({ name: 'Def', pattern: /def/, longer_alt: Identifier });
50
+ const Key = createToken({ name: 'Key', pattern: /key/, longer_alt: Identifier });
51
+ const Nullable = createToken({ name: 'Nullable', pattern: /nullable/, longer_alt: Identifier });
52
+ const ExposedAggregates = createToken({ name: 'ExposedAggregates', pattern: /exposedAggregates/, longer_alt: Identifier });
53
+ // Collection types
54
+ const ListType = createToken({ name: 'ListType', pattern: /List/, longer_alt: Identifier });
55
+ const SetType = createToken({ name: 'SetType', pattern: /Set/, longer_alt: Identifier });
56
+ const LAngle = createToken({ name: 'LAngle', pattern: /</ });
57
+ const RAngle = createToken({ name: 'RAngle', pattern: />/ });
58
+ // State keywords
59
+ const AsIs = createToken({ name: 'AsIs', pattern: /AS_IS/, longer_alt: Identifier });
60
+ const ToBe = createToken({ name: 'ToBe', pattern: /TO_BE/, longer_alt: Identifier });
61
+ const Meta = createToken({ name: 'Meta', pattern: /META/, longer_alt: Identifier });
62
+ const Concrete = createToken({ name: 'Concrete', pattern: /CONCRETE/, longer_alt: Identifier });
63
+ // Symbols
64
+ const LCurly = createToken({ name: 'LCurly', pattern: /{/ });
65
+ const RCurly = createToken({ name: 'RCurly', pattern: /}/ });
66
+ const LParen = createToken({ name: 'LParen', pattern: /\(/ });
67
+ const RParen = createToken({ name: 'RParen', pattern: /\)/ });
68
+ const LSquare = createToken({ name: 'LSquare', pattern: /\[/ });
69
+ const RSquare = createToken({ name: 'RSquare', pattern: /\]/ });
70
+ const Comma = createToken({ name: 'Comma', pattern: /,/ });
71
+ const Colon = createToken({ name: 'Colon', pattern: /:/ });
72
+ const Semicolon = createToken({ name: 'Semicolon', pattern: /;/ });
73
+ const Equals = createToken({ name: 'Equals', pattern: /=/ });
74
+ const Arrow = createToken({ name: 'Arrow', pattern: /->/ });
75
+ const DoubleArrow = createToken({ name: 'DoubleArrow', pattern: /<->/ });
76
+ const UpstreamDownstreamArrow = createToken({ name: 'UpstreamDownstreamArrow', pattern: /U->D|D<-U/ });
77
+ const DownstreamUpstreamArrow = createToken({ name: 'DownstreamUpstreamArrow', pattern: /D->U|U<-D/ });
78
+ // Literals
79
+ const StringLiteral = createToken({ name: 'StringLiteral', pattern: /"[^"]*"/ });
80
+ // Note: Identifier is defined earlier for longer_alt references
81
+ // All tokens in order (order matters for lexer)
82
+ const allTokens = [
83
+ WhiteSpace,
84
+ LineComment,
85
+ BlockComment,
86
+ // Multi-char operators first
87
+ DoubleArrow,
88
+ UpstreamDownstreamArrow,
89
+ DownstreamUpstreamArrow,
90
+ Arrow,
91
+ // Keywords before Identifier
92
+ ContextMap,
93
+ BoundedContext,
94
+ Aggregate,
95
+ Entity,
96
+ ValueObject,
97
+ DomainEvent,
98
+ Command,
99
+ Service,
100
+ Module,
101
+ Partnership,
102
+ SharedKernel,
103
+ CustomerSupplier,
104
+ UpstreamKw,
105
+ DownstreamKw,
106
+ UpstreamShort,
107
+ DownstreamShort,
108
+ OHS,
109
+ PL,
110
+ ACL,
111
+ CF,
112
+ Contains,
113
+ Implements,
114
+ Type,
115
+ State,
116
+ DomainVisionStatement,
117
+ Responsibilities,
118
+ ImplementationTechnology,
119
+ KnowledgeLevel,
120
+ AggregateRoot,
121
+ Def,
122
+ Key,
123
+ Nullable,
124
+ ExposedAggregates,
125
+ ListType,
126
+ SetType,
127
+ AsIs,
128
+ ToBe,
129
+ Meta,
130
+ Concrete,
131
+ // Symbols
132
+ LCurly,
133
+ RCurly,
134
+ LParen,
135
+ RParen,
136
+ LSquare,
137
+ RSquare,
138
+ LAngle,
139
+ RAngle,
140
+ Comma,
141
+ Colon,
142
+ Semicolon,
143
+ Equals,
144
+ // Literals
145
+ StringLiteral,
146
+ Identifier,
147
+ ];
148
+ const CMLLexer = new Lexer(allTokens);
149
+ // ============================================
150
+ // PARSER
151
+ // ============================================
152
+ class CMLParserClass extends CstParser {
153
+ constructor() {
154
+ super(allTokens);
155
+ this.performSelfAnalysis();
156
+ }
157
+ // Entry rule
158
+ cmlModel = this.RULE('cmlModel', () => {
159
+ this.MANY(() => {
160
+ this.OR([
161
+ { ALT: () => this.SUBRULE(this.contextMapDecl) },
162
+ { ALT: () => this.SUBRULE(this.boundedContextDecl) },
163
+ ]);
164
+ });
165
+ });
166
+ // Context Map declaration
167
+ contextMapDecl = this.RULE('contextMapDecl', () => {
168
+ this.CONSUME(ContextMap);
169
+ this.OPTION(() => this.CONSUME(Identifier));
170
+ this.CONSUME(LCurly);
171
+ this.MANY(() => {
172
+ this.OR([
173
+ { ALT: () => this.SUBRULE(this.contextMapType) },
174
+ { ALT: () => this.SUBRULE(this.contextMapState) },
175
+ { ALT: () => this.SUBRULE(this.contextMapContains) },
176
+ { ALT: () => this.SUBRULE(this.relationshipDecl) },
177
+ ]);
178
+ });
179
+ this.CONSUME(RCurly);
180
+ });
181
+ // type = SYSTEM_LANDSCAPE | ORGANIZATIONAL
182
+ contextMapType = this.RULE('contextMapType', () => {
183
+ this.CONSUME(Type);
184
+ this.OPTION(() => this.CONSUME(Equals));
185
+ this.CONSUME(Identifier); // SYSTEM_LANDSCAPE or ORGANIZATIONAL
186
+ });
187
+ // state = AS_IS | TO_BE
188
+ contextMapState = this.RULE('contextMapState', () => {
189
+ this.CONSUME(State);
190
+ this.OPTION(() => this.CONSUME(Equals));
191
+ this.OR([
192
+ { ALT: () => this.CONSUME(AsIs) },
193
+ { ALT: () => this.CONSUME(ToBe) },
194
+ ]);
195
+ });
196
+ contextMapContains = this.RULE('contextMapContains', () => {
197
+ this.CONSUME(Contains);
198
+ this.AT_LEAST_ONE_SEP({
199
+ SEP: Comma,
200
+ DEF: () => this.CONSUME(Identifier),
201
+ });
202
+ });
203
+ // Relationship declarations
204
+ relationshipDecl = this.RULE('relationshipDecl', () => {
205
+ this.OR([
206
+ { ALT: () => this.SUBRULE(this.symmetricRelationship) },
207
+ { ALT: () => this.SUBRULE(this.upstreamDownstreamRelationship) },
208
+ ]);
209
+ });
210
+ symmetricRelationship = this.RULE('symmetricRelationship', () => {
211
+ this.CONSUME(Identifier);
212
+ this.OR([
213
+ { ALT: () => this.CONSUME(Partnership) },
214
+ { ALT: () => this.CONSUME(SharedKernel) },
215
+ ]);
216
+ this.CONSUME2(Identifier);
217
+ });
218
+ // Upstream-downstream: Context1 [U,OHS,PL] -> [D,ACL] Context2
219
+ upstreamDownstreamRelationship = this.RULE('upstreamDownstreamRelationship', () => {
220
+ // First context name
221
+ this.CONSUME(Identifier);
222
+ // Optional upstream patterns [U,OHS,PL]
223
+ this.OPTION(() => {
224
+ this.CONSUME(LSquare);
225
+ this.SUBRULE(this.upstreamPatterns);
226
+ this.CONSUME(RSquare);
227
+ });
228
+ // Arrow
229
+ this.CONSUME(Arrow);
230
+ // Optional downstream patterns [D,ACL]
231
+ this.OPTION2(() => {
232
+ this.CONSUME2(LSquare);
233
+ this.SUBRULE(this.downstreamPatterns);
234
+ this.CONSUME2(RSquare);
235
+ });
236
+ // Second context name
237
+ this.CONSUME2(Identifier);
238
+ // Optional properties block
239
+ this.OPTION3(() => {
240
+ this.CONSUME(LCurly);
241
+ this.MANY(() => this.SUBRULE(this.relationshipProperty));
242
+ this.CONSUME(RCurly);
243
+ });
244
+ });
245
+ // [U,OHS,PL] or [U] or [Upstream,OHS]
246
+ upstreamPatterns = this.RULE('upstreamPatterns', () => {
247
+ this.OR([
248
+ { ALT: () => this.CONSUME(UpstreamShort) },
249
+ { ALT: () => this.CONSUME(UpstreamKw) },
250
+ ]);
251
+ this.MANY(() => {
252
+ this.CONSUME(Comma);
253
+ this.OR2([
254
+ { ALT: () => this.CONSUME(OHS) },
255
+ { ALT: () => this.CONSUME(PL) },
256
+ ]);
257
+ });
258
+ });
259
+ // [D,ACL] or [D] or [Downstream,CF]
260
+ downstreamPatterns = this.RULE('downstreamPatterns', () => {
261
+ this.OR([
262
+ { ALT: () => this.CONSUME(DownstreamShort) },
263
+ { ALT: () => this.CONSUME(DownstreamKw) },
264
+ ]);
265
+ this.MANY(() => {
266
+ this.CONSUME(Comma);
267
+ this.OR2([
268
+ { ALT: () => this.CONSUME(ACL) },
269
+ { ALT: () => this.CONSUME(CF) },
270
+ ]);
271
+ });
272
+ });
273
+ relationshipProperty = this.RULE('relationshipProperty', () => {
274
+ this.OR([
275
+ { ALT: () => this.SUBRULE(this.exposedAggregatesProperty) },
276
+ ]);
277
+ });
278
+ exposedAggregatesProperty = this.RULE('exposedAggregatesProperty', () => {
279
+ this.CONSUME(ExposedAggregates);
280
+ this.CONSUME(Equals);
281
+ this.CONSUME(Identifier);
282
+ this.MANY(() => {
283
+ this.CONSUME(Comma);
284
+ this.CONSUME2(Identifier);
285
+ });
286
+ });
287
+ // Bounded Context declaration
288
+ boundedContextDecl = this.RULE('boundedContextDecl', () => {
289
+ this.CONSUME(BoundedContext);
290
+ this.CONSUME(Identifier);
291
+ this.OPTION(() => {
292
+ this.CONSUME(Implements);
293
+ this.CONSUME2(Identifier);
294
+ });
295
+ this.CONSUME(LCurly);
296
+ this.MANY(() => {
297
+ this.OR([
298
+ { ALT: () => this.SUBRULE(this.domainVisionStatementDecl) },
299
+ { ALT: () => this.SUBRULE(this.responsibilitiesDecl) },
300
+ { ALT: () => this.SUBRULE(this.implementationTechnologyDecl) },
301
+ { ALT: () => this.SUBRULE(this.knowledgeLevelDecl) },
302
+ { ALT: () => this.SUBRULE(this.aggregateDecl) },
303
+ { ALT: () => this.SUBRULE(this.moduleDecl) },
304
+ ]);
305
+ });
306
+ this.CONSUME(RCurly);
307
+ });
308
+ domainVisionStatementDecl = this.RULE('domainVisionStatementDecl', () => {
309
+ this.CONSUME(DomainVisionStatement);
310
+ this.CONSUME(Equals);
311
+ this.CONSUME(StringLiteral);
312
+ });
313
+ responsibilitiesDecl = this.RULE('responsibilitiesDecl', () => {
314
+ this.CONSUME(Responsibilities);
315
+ this.CONSUME(Equals);
316
+ this.CONSUME(StringLiteral);
317
+ this.MANY(() => {
318
+ this.CONSUME(Comma);
319
+ this.CONSUME2(StringLiteral);
320
+ });
321
+ });
322
+ implementationTechnologyDecl = this.RULE('implementationTechnologyDecl', () => {
323
+ this.CONSUME(ImplementationTechnology);
324
+ this.CONSUME(Equals);
325
+ this.CONSUME(StringLiteral);
326
+ });
327
+ knowledgeLevelDecl = this.RULE('knowledgeLevelDecl', () => {
328
+ this.CONSUME(KnowledgeLevel);
329
+ this.CONSUME(Equals);
330
+ this.OR([
331
+ { ALT: () => this.CONSUME(Meta) },
332
+ { ALT: () => this.CONSUME(Concrete) },
333
+ ]);
334
+ });
335
+ // Module declaration
336
+ moduleDecl = this.RULE('moduleDecl', () => {
337
+ this.CONSUME(Module);
338
+ this.CONSUME(Identifier);
339
+ this.CONSUME(LCurly);
340
+ this.MANY(() => this.SUBRULE(this.aggregateDecl));
341
+ this.CONSUME(RCurly);
342
+ });
343
+ // Aggregate declaration
344
+ aggregateDecl = this.RULE('aggregateDecl', () => {
345
+ this.CONSUME(Aggregate);
346
+ this.CONSUME(Identifier);
347
+ this.CONSUME(LCurly);
348
+ this.MANY(() => {
349
+ this.OR([
350
+ { ALT: () => this.SUBRULE(this.responsibilitiesDecl) },
351
+ { ALT: () => this.SUBRULE(this.knowledgeLevelDecl) },
352
+ { ALT: () => this.SUBRULE(this.entityDecl) },
353
+ { ALT: () => this.SUBRULE(this.valueObjectDecl) },
354
+ { ALT: () => this.SUBRULE(this.domainEventDecl) },
355
+ { ALT: () => this.SUBRULE(this.commandDecl) },
356
+ { ALT: () => this.SUBRULE(this.serviceDecl) },
357
+ ]);
358
+ });
359
+ this.CONSUME(RCurly);
360
+ });
361
+ // Entity declaration
362
+ entityDecl = this.RULE('entityDecl', () => {
363
+ this.CONSUME(Entity);
364
+ this.CONSUME(Identifier);
365
+ this.OPTION(() => {
366
+ this.CONSUME(LCurly);
367
+ this.MANY(() => {
368
+ this.OR([
369
+ { ALT: () => this.SUBRULE(this.aggregateRootDecl) },
370
+ { ALT: () => this.SUBRULE(this.attributeDecl) },
371
+ { ALT: () => this.SUBRULE(this.operationDecl) },
372
+ ]);
373
+ });
374
+ this.CONSUME(RCurly);
375
+ });
376
+ });
377
+ aggregateRootDecl = this.RULE('aggregateRootDecl', () => {
378
+ this.CONSUME(AggregateRoot);
379
+ });
380
+ // Value Object declaration
381
+ valueObjectDecl = this.RULE('valueObjectDecl', () => {
382
+ this.CONSUME(ValueObject);
383
+ this.CONSUME(Identifier);
384
+ this.OPTION(() => {
385
+ this.CONSUME(LCurly);
386
+ this.MANY(() => this.SUBRULE(this.attributeDecl));
387
+ this.CONSUME(RCurly);
388
+ });
389
+ });
390
+ // Domain Event declaration
391
+ domainEventDecl = this.RULE('domainEventDecl', () => {
392
+ this.CONSUME(DomainEvent);
393
+ this.CONSUME(Identifier);
394
+ this.OPTION(() => {
395
+ this.CONSUME(LCurly);
396
+ this.MANY(() => this.SUBRULE(this.attributeDecl));
397
+ this.CONSUME(RCurly);
398
+ });
399
+ });
400
+ // Command declaration
401
+ commandDecl = this.RULE('commandDecl', () => {
402
+ this.CONSUME(Command);
403
+ this.CONSUME(Identifier);
404
+ this.OPTION(() => {
405
+ this.CONSUME(LCurly);
406
+ this.MANY(() => this.SUBRULE(this.attributeDecl));
407
+ this.CONSUME(RCurly);
408
+ });
409
+ });
410
+ // Service declaration
411
+ serviceDecl = this.RULE('serviceDecl', () => {
412
+ this.CONSUME(Service);
413
+ this.CONSUME(Identifier);
414
+ this.OPTION(() => {
415
+ this.CONSUME(LCurly);
416
+ this.MANY(() => this.SUBRULE(this.operationDecl));
417
+ this.CONSUME(RCurly);
418
+ });
419
+ });
420
+ // Attribute declaration: Type name key? nullable? ;?
421
+ // Also supports: List<Type> name or Set<Type> name
422
+ // Attribute name - can be identifier or certain keywords used as names
423
+ attributeName = this.RULE('attributeName', () => {
424
+ this.OR([
425
+ { ALT: () => this.CONSUME(Identifier) },
426
+ { ALT: () => this.CONSUME(Type) }, // 'type' is often used as attr name
427
+ { ALT: () => this.CONSUME(State) }, // 'state' is often used as attr name
428
+ { ALT: () => this.CONSUME(Key) }, // 'key' can be an attr name
429
+ { ALT: () => this.CONSUME(Service) }, // 'service' can be an attr name
430
+ { ALT: () => this.CONSUME(Module) }, // 'module' can be an attr name
431
+ ]);
432
+ });
433
+ attributeDecl = this.RULE('attributeDecl', () => {
434
+ // Type (can be collection type like List<String>)
435
+ this.OR([
436
+ {
437
+ ALT: () => {
438
+ this.OR2([
439
+ { ALT: () => this.CONSUME(ListType) },
440
+ { ALT: () => this.CONSUME(SetType) },
441
+ ]);
442
+ this.CONSUME(LAngle);
443
+ this.CONSUME(Identifier); // inner type
444
+ this.CONSUME(RAngle);
445
+ },
446
+ },
447
+ { ALT: () => this.CONSUME2(Identifier) }, // simple type
448
+ ]);
449
+ // Name - can be identifier or keyword
450
+ this.SUBRULE(this.attributeName);
451
+ // Optional modifiers (after name)
452
+ this.OPTION(() => this.CONSUME2(Key));
453
+ this.OPTION2(() => this.CONSUME(Nullable));
454
+ // Optional semicolon
455
+ this.OPTION3(() => this.CONSUME(Semicolon));
456
+ });
457
+ // Operation declaration
458
+ operationDecl = this.RULE('operationDecl', () => {
459
+ this.CONSUME(Def);
460
+ this.CONSUME(Identifier); // return type or void
461
+ this.CONSUME2(Identifier); // method name
462
+ this.CONSUME(LParen);
463
+ this.OPTION(() => {
464
+ this.SUBRULE(this.parameterDecl);
465
+ this.MANY(() => {
466
+ this.CONSUME(Comma);
467
+ this.SUBRULE2(this.parameterDecl);
468
+ });
469
+ });
470
+ this.CONSUME(RParen);
471
+ });
472
+ parameterDecl = this.RULE('parameterDecl', () => {
473
+ this.CONSUME(Identifier); // type
474
+ this.CONSUME2(Identifier); // name
475
+ });
476
+ }
477
+ // Create parser instance
478
+ const parser = new CMLParserClass();
479
+ function getToken(children, tokenName, index = 0) {
480
+ const tokens = children[tokenName];
481
+ if (tokens && tokens.length > index) {
482
+ return tokens[index];
483
+ }
484
+ return undefined;
485
+ }
486
+ function getNode(children, nodeName, index = 0) {
487
+ const nodes = children[nodeName];
488
+ if (nodes && nodes.length > index) {
489
+ return nodes[index];
490
+ }
491
+ return undefined;
492
+ }
493
+ function getAllNodes(children, nodeName) {
494
+ const nodes = children[nodeName];
495
+ return (nodes || []);
496
+ }
497
+ function getAllTokens(children, tokenName) {
498
+ const tokens = children[tokenName];
499
+ return (tokens || []);
500
+ }
501
+ function stripQuotes(str) {
502
+ return str.replace(/^"|"$/g, '');
503
+ }
504
+ // Visitor to build typed model from CST
505
+ function visitCmlModel(cst) {
506
+ const model = {
507
+ name: 'Untitled',
508
+ boundedContexts: [],
509
+ };
510
+ const children = cst.children;
511
+ // Process context maps
512
+ const contextMapNodes = getAllNodes(children, 'contextMapDecl');
513
+ if (contextMapNodes.length > 0) {
514
+ model.contextMap = visitContextMap(contextMapNodes[0]);
515
+ }
516
+ // Process bounded contexts
517
+ const bcNodes = getAllNodes(children, 'boundedContextDecl');
518
+ for (const bcNode of bcNodes) {
519
+ model.boundedContexts.push(visitBoundedContext(bcNode));
520
+ }
521
+ return model;
522
+ }
523
+ function visitContextMap(cst) {
524
+ const children = cst.children;
525
+ const nameToken = getToken(children, 'Identifier');
526
+ const contextMap = {
527
+ id: uuidv4(),
528
+ name: nameToken?.image || 'MainContextMap',
529
+ boundedContexts: [],
530
+ relationships: [],
531
+ };
532
+ // Process state
533
+ const stateNodes = getAllNodes(children, 'contextMapState');
534
+ if (stateNodes.length > 0) {
535
+ const stateChildren = stateNodes[0].children;
536
+ if (stateChildren['AsIs']) {
537
+ contextMap.state = 'AS_IS';
538
+ }
539
+ else if (stateChildren['ToBe']) {
540
+ contextMap.state = 'TO_BE';
541
+ }
542
+ }
543
+ // Process contains
544
+ const containsNodes = getAllNodes(children, 'contextMapContains');
545
+ for (const containsNode of containsNodes) {
546
+ const identifiers = getAllTokens(containsNode.children, 'Identifier');
547
+ for (const id of identifiers) {
548
+ contextMap.boundedContexts.push(id.image);
549
+ }
550
+ }
551
+ // Process relationships
552
+ const relNodes = getAllNodes(children, 'relationshipDecl');
553
+ for (const relNode of relNodes) {
554
+ const rel = visitRelationship(relNode);
555
+ if (rel) {
556
+ contextMap.relationships.push(rel);
557
+ }
558
+ }
559
+ return contextMap;
560
+ }
561
+ function visitRelationship(cst) {
562
+ const children = cst.children;
563
+ // Symmetric relationship
564
+ const symRelNode = getNode(children, 'symmetricRelationship');
565
+ if (symRelNode) {
566
+ const symChildren = symRelNode.children;
567
+ const identifiers = getAllTokens(symChildren, 'Identifier');
568
+ let type = 'Partnership';
569
+ if (symChildren['SharedKernel']) {
570
+ type = 'SharedKernel';
571
+ }
572
+ return {
573
+ id: uuidv4(),
574
+ type,
575
+ participant1: identifiers[0]?.image || '',
576
+ participant2: identifiers[1]?.image || '',
577
+ };
578
+ }
579
+ // Upstream-Downstream relationship
580
+ // Format: Context1 [U,OHS,PL] -> [D,ACL] Context2
581
+ const udRelNode = getNode(children, 'upstreamDownstreamRelationship');
582
+ if (udRelNode) {
583
+ const udChildren = udRelNode.children;
584
+ const identifiers = getAllTokens(udChildren, 'Identifier');
585
+ // First identifier is upstream, second is downstream
586
+ const rel = {
587
+ id: uuidv4(),
588
+ type: 'UpstreamDownstream',
589
+ upstream: identifiers[0]?.image || '',
590
+ downstream: identifiers[1]?.image || '',
591
+ upstreamPatterns: [],
592
+ downstreamPatterns: [],
593
+ };
594
+ // Get patterns
595
+ const upstreamPatternsNode = getNode(udChildren, 'upstreamPatterns');
596
+ if (upstreamPatternsNode) {
597
+ const upChildren = upstreamPatternsNode.children;
598
+ const ohsTokens = getAllTokens(upChildren, 'OHS');
599
+ const plTokens = getAllTokens(upChildren, 'PL');
600
+ if (ohsTokens.length > 0)
601
+ rel.upstreamPatterns.push('OHS');
602
+ if (plTokens.length > 0)
603
+ rel.upstreamPatterns.push('PL');
604
+ }
605
+ const downstreamPatternsNode = getNode(udChildren, 'downstreamPatterns');
606
+ if (downstreamPatternsNode) {
607
+ const downChildren = downstreamPatternsNode.children;
608
+ const aclTokens = getAllTokens(downChildren, 'ACL');
609
+ const cfTokens = getAllTokens(downChildren, 'CF');
610
+ if (aclTokens.length > 0)
611
+ rel.downstreamPatterns.push('ACL');
612
+ if (cfTokens.length > 0)
613
+ rel.downstreamPatterns.push('CF');
614
+ }
615
+ // Get exposed aggregates
616
+ const relPropNodes = getAllNodes(udChildren, 'relationshipProperty');
617
+ for (const propNode of relPropNodes) {
618
+ const expAggNode = getNode(propNode.children, 'exposedAggregatesProperty');
619
+ if (expAggNode) {
620
+ const aggIds = getAllTokens(expAggNode.children, 'Identifier');
621
+ rel.exposedAggregates = aggIds.map(t => t.image);
622
+ }
623
+ }
624
+ return rel;
625
+ }
626
+ return undefined;
627
+ }
628
+ function visitBoundedContext(cst) {
629
+ const children = cst.children;
630
+ const nameToken = getToken(children, 'Identifier');
631
+ const bc = {
632
+ id: uuidv4(),
633
+ name: nameToken?.image || 'UnnamedContext',
634
+ aggregates: [],
635
+ modules: [],
636
+ };
637
+ // Domain vision statement
638
+ const dvsNodes = getAllNodes(children, 'domainVisionStatementDecl');
639
+ if (dvsNodes.length > 0) {
640
+ const strToken = getToken(dvsNodes[0].children, 'StringLiteral');
641
+ if (strToken) {
642
+ bc.domainVisionStatement = stripQuotes(strToken.image);
643
+ }
644
+ }
645
+ // Responsibilities
646
+ const respNodes = getAllNodes(children, 'responsibilitiesDecl');
647
+ if (respNodes.length > 0) {
648
+ const strTokens = getAllTokens(respNodes[0].children, 'StringLiteral');
649
+ bc.responsibilities = strTokens.map(t => stripQuotes(t.image));
650
+ }
651
+ // Implementation technology
652
+ const implTechNodes = getAllNodes(children, 'implementationTechnologyDecl');
653
+ if (implTechNodes.length > 0) {
654
+ const strToken = getToken(implTechNodes[0].children, 'StringLiteral');
655
+ if (strToken) {
656
+ bc.implementationTechnology = stripQuotes(strToken.image);
657
+ }
658
+ }
659
+ // Knowledge level
660
+ const klNodes = getAllNodes(children, 'knowledgeLevelDecl');
661
+ if (klNodes.length > 0) {
662
+ const klChildren = klNodes[0].children;
663
+ if (klChildren['Meta']) {
664
+ bc.knowledgeLevel = 'META';
665
+ }
666
+ else if (klChildren['Concrete']) {
667
+ bc.knowledgeLevel = 'CONCRETE';
668
+ }
669
+ }
670
+ // Aggregates
671
+ const aggNodes = getAllNodes(children, 'aggregateDecl');
672
+ for (const aggNode of aggNodes) {
673
+ bc.aggregates.push(visitAggregate(aggNode));
674
+ }
675
+ // Modules
676
+ const modNodes = getAllNodes(children, 'moduleDecl');
677
+ for (const modNode of modNodes) {
678
+ const modChildren = modNode.children;
679
+ const modName = getToken(modChildren, 'Identifier')?.image || 'UnnamedModule';
680
+ const module = {
681
+ id: uuidv4(),
682
+ name: modName,
683
+ aggregates: [],
684
+ };
685
+ const modAggNodes = getAllNodes(modChildren, 'aggregateDecl');
686
+ for (const aggNode of modAggNodes) {
687
+ module.aggregates.push(visitAggregate(aggNode));
688
+ }
689
+ bc.modules.push(module);
690
+ }
691
+ return bc;
692
+ }
693
+ function visitAggregate(cst) {
694
+ const children = cst.children;
695
+ const nameToken = getToken(children, 'Identifier');
696
+ const agg = {
697
+ id: uuidv4(),
698
+ name: nameToken?.image || 'UnnamedAggregate',
699
+ entities: [],
700
+ valueObjects: [],
701
+ domainEvents: [],
702
+ commands: [],
703
+ services: [],
704
+ };
705
+ // Responsibilities
706
+ const respNodes = getAllNodes(children, 'responsibilitiesDecl');
707
+ if (respNodes.length > 0) {
708
+ const strTokens = getAllTokens(respNodes[0].children, 'StringLiteral');
709
+ agg.responsibilities = strTokens.map(t => stripQuotes(t.image));
710
+ }
711
+ // Knowledge level
712
+ const klNodes = getAllNodes(children, 'knowledgeLevelDecl');
713
+ if (klNodes.length > 0) {
714
+ const klChildren = klNodes[0].children;
715
+ if (klChildren['Meta']) {
716
+ agg.knowledgeLevel = 'META';
717
+ }
718
+ else if (klChildren['Concrete']) {
719
+ agg.knowledgeLevel = 'CONCRETE';
720
+ }
721
+ }
722
+ // Entities
723
+ const entityNodes = getAllNodes(children, 'entityDecl');
724
+ for (const entityNode of entityNodes) {
725
+ const entity = visitEntity(entityNode);
726
+ if (entity.aggregateRoot) {
727
+ agg.aggregateRoot = entity;
728
+ }
729
+ agg.entities.push(entity);
730
+ }
731
+ // Value Objects
732
+ const voNodes = getAllNodes(children, 'valueObjectDecl');
733
+ for (const voNode of voNodes) {
734
+ agg.valueObjects.push(visitValueObject(voNode));
735
+ }
736
+ // Domain Events
737
+ const eventNodes = getAllNodes(children, 'domainEventDecl');
738
+ for (const eventNode of eventNodes) {
739
+ agg.domainEvents.push(visitDomainEvent(eventNode));
740
+ }
741
+ // Commands
742
+ const cmdNodes = getAllNodes(children, 'commandDecl');
743
+ for (const cmdNode of cmdNodes) {
744
+ agg.commands.push(visitCommand(cmdNode));
745
+ }
746
+ // Services
747
+ const svcNodes = getAllNodes(children, 'serviceDecl');
748
+ for (const svcNode of svcNodes) {
749
+ agg.services.push(visitService(svcNode));
750
+ }
751
+ return agg;
752
+ }
753
+ function visitEntity(cst) {
754
+ const children = cst.children;
755
+ const nameToken = getToken(children, 'Identifier');
756
+ const entity = {
757
+ id: uuidv4(),
758
+ name: nameToken?.image || 'UnnamedEntity',
759
+ attributes: [],
760
+ operations: [],
761
+ };
762
+ // Check for aggregate root
763
+ const aggRootNodes = getAllNodes(children, 'aggregateRootDecl');
764
+ if (aggRootNodes.length > 0) {
765
+ entity.aggregateRoot = true;
766
+ }
767
+ // Attributes
768
+ const attrNodes = getAllNodes(children, 'attributeDecl');
769
+ for (const attrNode of attrNodes) {
770
+ entity.attributes.push(visitAttribute(attrNode));
771
+ }
772
+ // Operations
773
+ const opNodes = getAllNodes(children, 'operationDecl');
774
+ for (const opNode of opNodes) {
775
+ entity.operations.push(visitOperation(opNode));
776
+ }
777
+ return entity;
778
+ }
779
+ function visitValueObject(cst) {
780
+ const children = cst.children;
781
+ const nameToken = getToken(children, 'Identifier');
782
+ const vo = {
783
+ id: uuidv4(),
784
+ name: nameToken?.image || 'UnnamedValueObject',
785
+ attributes: [],
786
+ };
787
+ // Attributes
788
+ const attrNodes = getAllNodes(children, 'attributeDecl');
789
+ for (const attrNode of attrNodes) {
790
+ vo.attributes.push(visitAttribute(attrNode));
791
+ }
792
+ return vo;
793
+ }
794
+ function visitDomainEvent(cst) {
795
+ const children = cst.children;
796
+ const nameToken = getToken(children, 'Identifier');
797
+ const event = {
798
+ id: uuidv4(),
799
+ name: nameToken?.image || 'UnnamedEvent',
800
+ attributes: [],
801
+ };
802
+ // Attributes
803
+ const attrNodes = getAllNodes(children, 'attributeDecl');
804
+ for (const attrNode of attrNodes) {
805
+ event.attributes.push(visitAttribute(attrNode));
806
+ }
807
+ return event;
808
+ }
809
+ function visitCommand(cst) {
810
+ const children = cst.children;
811
+ const nameToken = getToken(children, 'Identifier');
812
+ const cmd = {
813
+ id: uuidv4(),
814
+ name: nameToken?.image || 'UnnamedCommand',
815
+ attributes: [],
816
+ };
817
+ // Attributes
818
+ const attrNodes = getAllNodes(children, 'attributeDecl');
819
+ for (const attrNode of attrNodes) {
820
+ cmd.attributes.push(visitAttribute(attrNode));
821
+ }
822
+ return cmd;
823
+ }
824
+ function visitService(cst) {
825
+ const children = cst.children;
826
+ const nameToken = getToken(children, 'Identifier');
827
+ const svc = {
828
+ id: uuidv4(),
829
+ name: nameToken?.image || 'UnnamedService',
830
+ operations: [],
831
+ };
832
+ // Operations
833
+ const opNodes = getAllNodes(children, 'operationDecl');
834
+ for (const opNode of opNodes) {
835
+ svc.operations.push(visitOperation(opNode));
836
+ }
837
+ return svc;
838
+ }
839
+ function visitAttribute(cst) {
840
+ const children = cst.children;
841
+ const identifiers = getAllTokens(children, 'Identifier');
842
+ let type;
843
+ let name;
844
+ // Extract attribute name from attributeName subrule
845
+ const attrNameNode = getNode(children, 'attributeName');
846
+ if (attrNameNode) {
847
+ const nameChildren = attrNameNode.children;
848
+ // Try to get name from any of the possible tokens
849
+ const nameToken = getToken(nameChildren, 'Identifier') ||
850
+ getToken(nameChildren, 'Type') ||
851
+ getToken(nameChildren, 'State') ||
852
+ getToken(nameChildren, 'Key') ||
853
+ getToken(nameChildren, 'Service') ||
854
+ getToken(nameChildren, 'Module');
855
+ name = nameToken?.image || 'unnamed';
856
+ }
857
+ else {
858
+ // Fallback for old structure
859
+ name = identifiers[1]?.image || 'unnamed';
860
+ }
861
+ // Check for collection types (List<Type> or Set<Type>)
862
+ if (children['ListType'] || children['SetType']) {
863
+ const collectionType = children['ListType'] ? 'List' : 'Set';
864
+ const innerType = identifiers[0]?.image || 'Object';
865
+ type = `${collectionType}<${innerType}>`;
866
+ }
867
+ else {
868
+ // Simple type: Type name
869
+ type = identifiers[0]?.image || 'String';
870
+ }
871
+ const attr = { type, name };
872
+ if (children['Key']) {
873
+ attr.key = true;
874
+ }
875
+ if (children['Nullable']) {
876
+ attr.nullable = true;
877
+ }
878
+ return attr;
879
+ }
880
+ function visitOperation(cst) {
881
+ const children = cst.children;
882
+ const identifiers = getAllTokens(children, 'Identifier');
883
+ const op = {
884
+ returnType: identifiers[0]?.image || 'void',
885
+ name: identifiers[1]?.image || 'unnamed',
886
+ parameters: [],
887
+ };
888
+ // Parameters
889
+ const paramNodes = getAllNodes(children, 'parameterDecl');
890
+ for (const paramNode of paramNodes) {
891
+ const paramIds = getAllTokens(paramNode.children, 'Identifier');
892
+ op.parameters.push({
893
+ type: paramIds[0]?.image || 'Object',
894
+ name: paramIds[1]?.image || 'param',
895
+ });
896
+ }
897
+ return op;
898
+ }
899
+ export function parseCML(text) {
900
+ // Lexing
901
+ const lexResult = CMLLexer.tokenize(text);
902
+ if (lexResult.errors.length > 0) {
903
+ return {
904
+ success: false,
905
+ errors: lexResult.errors.map(e => ({
906
+ message: e.message,
907
+ line: e.line,
908
+ column: e.column,
909
+ })),
910
+ };
911
+ }
912
+ // Parsing
913
+ parser.input = lexResult.tokens;
914
+ const cst = parser.cmlModel();
915
+ if (parser.errors.length > 0) {
916
+ return {
917
+ success: false,
918
+ errors: parser.errors.map(e => ({
919
+ message: e.message,
920
+ line: e.token?.startLine,
921
+ column: e.token?.startColumn,
922
+ })),
923
+ };
924
+ }
925
+ // Build AST
926
+ const model = visitCmlModel(cst);
927
+ return {
928
+ success: true,
929
+ model,
930
+ errors: [],
931
+ };
932
+ }
933
+ export { CMLLexer, CMLParserClass as CMLParser };
934
+ //# sourceMappingURL=parser.js.map