1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.mal_lang.lib;
18
19 import java.util.ArrayList;
20 import java.util.List;
21 import java.util.Optional;
22
23 public class AST {
24 private List<Category> categories = new ArrayList<>();
25 private List<Association> associations = new ArrayList<>();
26 private List<Define> defines = new ArrayList<>();
27
28 @Override
29 public String toString() {
30 var sb = new StringBuilder();
31 sb.append(String.format("%s,%n", Define.listToString(defines, 0)));
32 sb.append(String.format("%s,%n", Category.listToString(categories, 0)));
33 sb.append(String.format("%s%n", Association.listToString(associations, 0)));
34 return sb.toString();
35 }
36
37 public void include(AST other) {
38 this.categories.addAll(other.categories);
39 this.associations.addAll(other.associations);
40 this.defines.addAll(other.defines);
41 }
42
43 public List<Category> getCategories() {
44 var categories = new ArrayList<Category>();
45 categories.addAll(this.categories);
46 return categories;
47 }
48
49 public void addCategory(Category category) {
50 this.categories.add(category);
51 }
52
53 public List<Association> getAssociations() {
54 var associations = new ArrayList<Association>();
55 associations.addAll(this.associations);
56 return associations;
57 }
58
59 public void addAssociations(List<Association> associations) {
60 this.associations.addAll(associations);
61 }
62
63 public List<Define> getDefines() {
64 var defines = new ArrayList<Define>();
65 defines.addAll(this.defines);
66 return defines;
67 }
68
69 public void addDefine(Define define) {
70 this.defines.add(define);
71 }
72
73 public static class ID extends Position {
74 public final String id;
75
76 public ID(Position pos, String id) {
77 super(pos);
78 this.id = id;
79 }
80
81 @Override
82 public String toString() {
83 return String.format("ID(%s, \"%s\")", posString(), id);
84 }
85 }
86
87 public static class Define extends Position {
88 public final ID key;
89 public final String value;
90
91 public Define(Position pos, ID key, String value) {
92 super(pos);
93 this.key = key;
94 this.value = value;
95 }
96
97 @Override
98 public String toString() {
99 return String.format("Define(%s, %s, \"%s\")", posString(), key.toString(), value);
100 }
101
102 public static String listToString(List<Define> defines, int spaces) {
103 var indent = " ".repeat(spaces);
104 var sb = new StringBuilder();
105 sb.append(String.format("%sdefines = {%n", indent));
106 for (int i = 0; i < defines.size(); i++) {
107 sb.append(String.format("%s %s", indent, defines.get(i).toString()));
108 if (i < defines.size() - 1) {
109 sb.append(',');
110 }
111 sb.append(String.format("%n"));
112 }
113 sb.append(String.format("%s}", indent));
114 return sb.toString();
115 }
116 }
117
118 public static class Meta extends Position {
119 public final ID type;
120 public final String string;
121
122 public Meta(Position pos, ID type, String string) {
123 super(pos);
124 this.type = type;
125 this.string = string;
126 }
127
128 @Override
129 public String toString() {
130 return String.format("Meta(%s, %s, \"%s\")", posString(), type.toString(), string);
131 }
132
133 public static String listToString(List<Meta> meta, int spaces) {
134 var indent = " ".repeat(spaces);
135 var sb = new StringBuilder();
136 sb.append(String.format("%smeta = {%n", indent));
137 for (int i = 0; i < meta.size(); i++) {
138 sb.append(String.format("%s %s", indent, meta.get(i).toString()));
139 if (i < meta.size() - 1) {
140 sb.append(',');
141 }
142 sb.append(String.format("%n"));
143 }
144 sb.append(String.format("%s}", indent));
145 return sb.toString();
146 }
147 }
148
149 public static class Category extends Position {
150 public final ID name;
151 public final List<Meta> meta;
152 public final List<Asset> assets;
153
154 public Category(Position pos, ID name, List<Meta> meta, List<Asset> assets) {
155 super(pos);
156 this.name = name;
157 this.meta = meta;
158 this.assets = assets;
159 }
160
161 public String toString(int spaces) {
162 var indent = " ".repeat(spaces);
163 var sb = new StringBuilder();
164 sb.append(String.format("%sCategory(%s, %s,%n", indent, posString(), name.toString()));
165 sb.append(String.format("%s,%n", Meta.listToString(meta, spaces + 2)));
166 sb.append(String.format("%s%n", Asset.listToString(assets, spaces + 2)));
167 sb.append(String.format("%s)", indent));
168 return sb.toString();
169 }
170
171 public static String listToString(List<Category> categories, int spaces) {
172 var indent = " ".repeat(spaces);
173 var sb = new StringBuilder();
174 sb.append(String.format("%scategories = {%n", indent));
175 for (int i = 0; i < categories.size(); i++) {
176 sb.append(String.format("%s", categories.get(i).toString(spaces + 2)));
177 if (i < categories.size() - 1) {
178 sb.append(',');
179 }
180 sb.append(String.format("%n"));
181 }
182 sb.append(String.format("%s}", indent));
183 return sb.toString();
184 }
185 }
186
187 public static class Asset extends Position {
188 public final boolean isAbstract;
189 public final ID name;
190 public final Optional<ID> parent;
191 public final List<Meta> meta;
192 public final List<AttackStep> attackSteps;
193 public final List<Variable> variables;
194
195 public Asset(
196 Position pos,
197 boolean isAbstract,
198 ID name,
199 Optional<ID> parent,
200 List<Meta> meta,
201 List<AttackStep> attackSteps,
202 List<Variable> variables) {
203 super(pos);
204 this.isAbstract = isAbstract;
205 this.name = name;
206 this.parent = parent;
207 this.meta = meta;
208 this.attackSteps = attackSteps;
209 this.variables = variables;
210 }
211
212 public String toString(int spaces) {
213 var indent = " ".repeat(spaces);
214 var sb = new StringBuilder();
215 sb.append(
216 String.format(
217 "%sAsset(%s, %s, %s, %s,%n",
218 indent,
219 posString(),
220 isAbstract ? "ABSTRACT" : "NOT_ABSTRACT",
221 name.toString(),
222 parent.isEmpty()
223 ? "NO_PARENT"
224 : String.format("PARENT(%s)", parent.get().toString())));
225 sb.append(String.format("%s,%n", Meta.listToString(meta, spaces + 2)));
226 sb.append(String.format("%s,%n", AttackStep.listToString(attackSteps, spaces + 2)));
227 sb.append(String.format("%s%n", Variable.listToString(variables, spaces + 2)));
228 sb.append(String.format("%s)", indent));
229 return sb.toString();
230 }
231
232 public static String listToString(List<Asset> assets, int spaces) {
233 var indent = " ".repeat(spaces);
234 var sb = new StringBuilder();
235 sb.append(String.format("%sassets = {%n", indent));
236 for (int i = 0; i < assets.size(); i++) {
237 sb.append(String.format("%s", assets.get(i).toString(spaces + 2)));
238 if (i < assets.size() - 1) {
239 sb.append(',');
240 }
241 sb.append(String.format("%n"));
242 }
243 sb.append(String.format("%s}", indent));
244 return sb.toString();
245 }
246 }
247
248 public enum AttackStepType {
249 ALL,
250 ANY,
251 DEFENSE,
252 EXIST,
253 NOTEXIST
254 }
255
256 public static class AttackStep extends Position {
257 public final AttackStepType type;
258 public final ID name;
259 public final List<ID> tags;
260 public final Optional<List<CIA>> cia;
261 public final Optional<TTCExpr> ttc;
262 public final List<Meta> meta;
263 public final Optional<Requires> requires;
264 public final Optional<Reaches> reaches;
265
266 public AttackStep(
267 Position pos,
268 AttackStepType type,
269 ID name,
270 List<ID> tags,
271 Optional<List<CIA>> cia,
272 Optional<TTCExpr> ttc,
273 List<Meta> meta,
274 Optional<Requires> requires,
275 Optional<Reaches> reaches) {
276 super(pos);
277 this.type = type;
278 this.name = name;
279 this.tags = tags;
280 this.cia = cia;
281 this.ttc = ttc;
282 this.meta = meta;
283 this.requires = requires;
284 this.reaches = reaches;
285 }
286
287 public String toString(int spaces) {
288 var indent = " ".repeat(spaces);
289 var sb = new StringBuilder();
290 sb.append(
291 String.format(
292 "%sAttackStep(%s, %s, %s,%n", indent, posString(), type.name(), name.toString()));
293 sb.append(String.format("%s tags = {", indent));
294 for (int i = 0; i < tags.size(); i++) {
295 if (i > 0) {
296 sb.append(", ");
297 }
298 sb.append(tags.get(i).toString());
299 }
300 sb.append(String.format("},%n"));
301 if (cia.isEmpty()) {
302 sb.append(String.format("%s cia = {},%n", indent));
303 } else {
304 sb.append(String.format("%s cia = {%s},%n", indent, CIA.listToString(cia.get())));
305 }
306 if (ttc.isEmpty()) {
307 sb.append(String.format("%s ttc = [],%n", indent));
308 } else {
309 sb.append(String.format("%s ttc = [%s],%n", indent, ttc.get().toString()));
310 }
311 sb.append(String.format("%s,%n", Meta.listToString(meta, spaces + 2)));
312 if (requires.isEmpty()) {
313 sb.append(String.format("%s NO_REQUIRES,%n", indent));
314 } else {
315 sb.append(String.format("%s,%n", requires.get().toString(spaces + 2)));
316 }
317 if (reaches.isEmpty()) {
318 sb.append(String.format("%s NO_REACHES%n", indent));
319 } else {
320 sb.append(String.format("%s%n", reaches.get().toString(spaces + 2)));
321 }
322 sb.append(String.format("%s)", indent));
323 return sb.toString();
324 }
325
326 public static String listToString(List<AttackStep> attackSteps, int spaces) {
327 var indent = " ".repeat(spaces);
328 var sb = new StringBuilder();
329 sb.append(String.format("%sattacksteps = {%n", indent));
330 for (int i = 0; i < attackSteps.size(); i++) {
331 sb.append(String.format("%s", attackSteps.get(i).toString(spaces + 2)));
332 if (i < attackSteps.size() - 1) {
333 sb.append(',');
334 }
335 sb.append(String.format("%n"));
336 }
337 sb.append(String.format("%s}", indent));
338 return sb.toString();
339 }
340 }
341
342 public enum CIA {
343 C,
344 I,
345 A;
346
347 public static String listToString(List<CIA> cia) {
348 var sb = new StringBuilder();
349 for (int i = 0; i < cia.size(); i++) {
350 if (i > 0) {
351 sb.append(", ");
352 }
353 sb.append(cia.get(i));
354 }
355 return sb.toString();
356 }
357 }
358
359 public abstract static class TTCExpr extends Position {
360 public TTCExpr(Position pos) {
361 super(pos);
362 }
363 }
364
365 public abstract static class TTCBinaryExpr extends TTCExpr {
366 public final TTCExpr lhs;
367 public final TTCExpr rhs;
368
369 public TTCBinaryExpr(Position pos, TTCExpr lhs, TTCExpr rhs) {
370 super(pos);
371 this.lhs = lhs;
372 this.rhs = rhs;
373 }
374 }
375
376 public static class TTCAddExpr extends TTCBinaryExpr {
377 public TTCAddExpr(Position pos, TTCExpr lhs, TTCExpr rhs) {
378 super(pos, lhs, rhs);
379 }
380
381 @Override
382 public String toString() {
383 return String.format("TTCAddExpr(%s, %s, %s)", posString(), lhs.toString(), rhs.toString());
384 }
385 }
386
387 public static class TTCSubExpr extends TTCBinaryExpr {
388 public TTCSubExpr(Position pos, TTCExpr lhs, TTCExpr rhs) {
389 super(pos, lhs, rhs);
390 }
391
392 @Override
393 public String toString() {
394 return String.format("TTCSubExpr(%s, %s, %s)", posString(), lhs.toString(), rhs.toString());
395 }
396 }
397
398 public static class TTCMulExpr extends TTCBinaryExpr {
399 public TTCMulExpr(Position pos, TTCExpr lhs, TTCExpr rhs) {
400 super(pos, lhs, rhs);
401 }
402
403 @Override
404 public String toString() {
405 return String.format("TTCMulExpr(%s, %s, %s)", posString(), lhs.toString(), rhs.toString());
406 }
407 }
408
409 public static class TTCDivExpr extends TTCBinaryExpr {
410 public TTCDivExpr(Position pos, TTCExpr lhs, TTCExpr rhs) {
411 super(pos, lhs, rhs);
412 }
413
414 @Override
415 public String toString() {
416 return String.format("TTCDivExpr(%s, %s, %s)", posString(), lhs.toString(), rhs.toString());
417 }
418 }
419
420 public static class TTCPowExpr extends TTCBinaryExpr {
421 public TTCPowExpr(Position pos, TTCExpr lhs, TTCExpr rhs) {
422 super(pos, lhs, rhs);
423 }
424
425 @Override
426 public String toString() {
427 return String.format("TTCPowExpr(%s, %s, %s)", posString(), lhs.toString(), rhs.toString());
428 }
429 }
430
431 public static class TTCFuncExpr extends TTCExpr {
432 public final ID name;
433 public final List<Double> params;
434
435 public TTCFuncExpr(Position pos, ID name, List<Double> params) {
436 super(pos);
437 this.name = name;
438 this.params = params;
439 }
440
441 @Override
442 public String toString() {
443 var sb = new StringBuilder();
444 sb.append(String.format("TTCFuncExpr(%s, %s", posString(), name.toString()));
445 for (var p : params) {
446 sb.append(String.format(", %f", p));
447 }
448 sb.append(')');
449 return sb.toString();
450 }
451 }
452
453 public static class TTCNumExpr extends TTCExpr {
454 public final double value;
455
456 public TTCNumExpr(Position pos, double value) {
457 super(pos);
458 this.value = value;
459 }
460
461 @Override
462 public String toString() {
463 return String.format("TTCNumExpr(%s, %f)", posString(), value);
464 }
465 }
466
467 public static class Requires extends Position {
468 public final List<Expr> requires;
469
470 public Requires(Position pos, List<Expr> requires) {
471 super(pos);
472 this.requires = requires;
473 }
474
475 public String toString(int spaces) {
476 var indent = " ".repeat(spaces);
477 var sb = new StringBuilder();
478 sb.append(String.format("%sRequires(%s,%n", indent, posString()));
479 sb.append(String.format("%s%n", Expr.listToString(requires, "requires", spaces + 2)));
480 sb.append(String.format("%s)", indent));
481 return sb.toString();
482 }
483 }
484
485 public static class Reaches extends Position {
486 public final boolean inherits;
487 public final List<Expr> reaches;
488
489 public Reaches(Position pos, boolean inherits, List<Expr> reaches) {
490 super(pos);
491 this.inherits = inherits;
492 this.reaches = reaches;
493 }
494
495 public String toString(int spaces) {
496 var indent = " ".repeat(spaces);
497 var sb = new StringBuilder();
498 sb.append(
499 String.format(
500 "%sReaches(%s, %s,%n", indent, posString(), inherits ? "INHERITS" : "OVERRIDES"));
501 sb.append(String.format("%s%n", Expr.listToString(reaches, "reaches", spaces + 2)));
502 sb.append(String.format("%s)", indent));
503 return sb.toString();
504 }
505 }
506
507 public static class Variable extends Position {
508 public final ID name;
509 public final Expr expr;
510
511 public Variable(Position pos, ID name, Expr expr) {
512 super(pos);
513 this.name = name;
514 this.expr = expr;
515 }
516
517 @Override
518 public String toString() {
519 return String.format("Variable(%s, %s, %s)", posString(), name.toString(), expr.toString());
520 }
521
522 public static String listToString(List<Variable> variables, int spaces) {
523 var indent = " ".repeat(spaces);
524 var sb = new StringBuilder();
525 sb.append(String.format("%svariables = {%n", indent));
526 for (int i = 0; i < variables.size(); i++) {
527 sb.append(String.format("%s %s", indent, variables.get(i).toString()));
528 if (i < variables.size() - 1) {
529 sb.append(',');
530 }
531 sb.append(String.format("%n"));
532 }
533 sb.append(String.format("%s}", indent));
534 return sb.toString();
535 }
536 }
537
538 public abstract static class Expr extends Position {
539 public Expr(Position pos) {
540 super(pos);
541 }
542
543 public static String listToString(List<Expr> exprs, String name, int spaces) {
544 var indent = " ".repeat(spaces);
545 var sb = new StringBuilder();
546 sb.append(String.format("%s%s = {%n", indent, name));
547 for (int i = 0; i < exprs.size(); i++) {
548 sb.append(String.format("%s %s", indent, exprs.get(i).toString()));
549 if (i < exprs.size() - 1) {
550 sb.append(',');
551 }
552 sb.append(String.format("%n"));
553 }
554 sb.append(String.format("%s}", indent));
555 return sb.toString();
556 }
557 }
558
559 public abstract static class BinaryExpr extends Expr {
560 public final Expr lhs;
561 public final Expr rhs;
562
563 public BinaryExpr(Position pos, Expr lhs, Expr rhs) {
564 super(pos);
565 this.lhs = lhs;
566 this.rhs = rhs;
567 }
568 }
569
570 public static class UnionExpr extends BinaryExpr {
571 public UnionExpr(Position pos, Expr lhs, Expr rhs) {
572 super(pos, lhs, rhs);
573 }
574
575 @Override
576 public String toString() {
577 return String.format("UnionExpr(%s, %s, %s)", posString(), lhs.toString(), rhs.toString());
578 }
579 }
580
581 public static class DifferenceExpr extends BinaryExpr {
582 public DifferenceExpr(Position pos, Expr lhs, Expr rhs) {
583 super(pos, lhs, rhs);
584 }
585
586 @Override
587 public String toString() {
588 return String.format(
589 "DifferenceExpr(%s, %s, %s)", posString(), lhs.toString(), rhs.toString());
590 }
591 }
592
593 public static class IntersectionExpr extends BinaryExpr {
594 public IntersectionExpr(Position pos, Expr lhs, Expr rhs) {
595 super(pos, lhs, rhs);
596 }
597
598 @Override
599 public String toString() {
600 return String.format(
601 "IntersectionExpr(%s, %s, %s)", posString(), lhs.toString(), rhs.toString());
602 }
603 }
604
605 public static class StepExpr extends BinaryExpr {
606 public StepExpr(Position pos, Expr lhs, Expr rhs) {
607 super(pos, lhs, rhs);
608 }
609
610 @Override
611 public String toString() {
612 return String.format("StepExpr(%s, %s, %s)", posString(), lhs.toString(), rhs.toString());
613 }
614 }
615
616 public abstract static class UnaryExpr extends Expr {
617 public final Expr e;
618
619 public UnaryExpr(Position pos, Expr e) {
620 super(pos);
621 this.e = e;
622 }
623 }
624
625 public static class TransitiveExpr extends UnaryExpr {
626 public TransitiveExpr(Position pos, Expr e) {
627 super(pos, e);
628 }
629
630 @Override
631 public String toString() {
632 return String.format("TransitiveExpr(%s, %s)", posString(), e.toString());
633 }
634 }
635
636 public static class SubTypeExpr extends UnaryExpr {
637 public final ID subType;
638
639 public SubTypeExpr(Position pos, Expr e, ID subType) {
640 super(pos, e);
641 this.subType = subType;
642 }
643
644 @Override
645 public String toString() {
646 return String.format(
647 "SubTypeExpr(%s, %s, %s)", posString(), e.toString(), subType.toString());
648 }
649 }
650
651 public static class IDExpr extends Expr {
652 public final ID id;
653
654 public IDExpr(Position pos, ID id) {
655 super(pos);
656 this.id = id;
657 }
658
659 @Override
660 public String toString() {
661 return String.format("IDExpr(%s, %s)", posString(), id.toString());
662 }
663 }
664
665 public static class CallExpr extends Expr {
666 public final ID id;
667
668 public CallExpr(Position pos, ID id) {
669 super(pos);
670 this.id = id;
671 }
672
673 @Override
674 public String toString() {
675 return String.format("CallExpr(%s, %s)", posString(), id.toString());
676 }
677 }
678
679 public static class Association extends Position {
680 public final ID leftAsset;
681 public final ID leftField;
682 public final Multiplicity leftMult;
683 public final ID linkName;
684 public final Multiplicity rightMult;
685 public final ID rightField;
686 public final ID rightAsset;
687 public final List<Meta> meta;
688
689 public Association(
690 Position pos,
691 ID leftAsset,
692 ID leftField,
693 Multiplicity leftMult,
694 ID linkName,
695 Multiplicity rightMult,
696 ID rightField,
697 ID rightAsset,
698 List<Meta> meta) {
699 super(pos);
700 this.leftAsset = leftAsset;
701 this.leftField = leftField;
702 this.leftMult = leftMult;
703 this.linkName = linkName;
704 this.rightMult = rightMult;
705 this.rightField = rightField;
706 this.rightAsset = rightAsset;
707 this.meta = meta;
708 }
709
710 public String toString(int spaces) {
711 var indent = " ".repeat(spaces);
712 var sb = new StringBuilder();
713 sb.append(
714 String.format(
715 "%sAssociation(%s, %s, %s, %s, %s, %s, %s, %s,%n",
716 indent,
717 posString(),
718 leftAsset.toString(),
719 leftField.toString(),
720 leftMult.name(),
721 linkName.toString(),
722 rightMult.name(),
723 rightField.toString(),
724 rightAsset.toString()));
725 sb.append(String.format("%s%n", Meta.listToString(meta, spaces + 2)));
726 sb.append(String.format("%s)", indent));
727 return sb.toString();
728 }
729
730 public String toShortString() {
731 return String.format(
732 "%s [%s] <-- %s --> %s [%s]",
733 leftAsset.id, leftField.id, linkName.id, rightAsset.id, rightField.id);
734 }
735
736 public static String listToString(List<Association> associations, int spaces) {
737 var indent = " ".repeat(spaces);
738 var sb = new StringBuilder();
739 sb.append(String.format("%sassociations = {%n", indent));
740 for (int i = 0; i < associations.size(); i++) {
741 sb.append(String.format("%s", associations.get(i).toString(spaces + 2)));
742 if (i < associations.size() - 1) {
743 sb.append(',');
744 }
745 sb.append(String.format("%n"));
746 }
747 sb.append(String.format("%s}", indent));
748 return sb.toString();
749 }
750 }
751
752 public enum Multiplicity {
753 ZERO_OR_ONE("0..1"),
754 ZERO_OR_MORE("*"),
755 ONE("1"),
756 ONE_OR_MORE("1..*");
757
758 private String string;
759
760 private Multiplicity(String string) {
761 this.string = string;
762 }
763
764 @Override
765 public String toString() {
766 return string;
767 }
768 }
769 }