drools-builder 0.1.3 → 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.
- package/dist/index.cjs +199 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +69 -1
- package/dist/index.d.ts +69 -1
- package/dist/index.js +199 -7
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -614,8 +614,72 @@ ${indent}}`;
|
|
|
614
614
|
return `${cons.expression};`;
|
|
615
615
|
case "RawConsequence":
|
|
616
616
|
return `${cons.code};`;
|
|
617
|
+
case "ReturnConsequence":
|
|
618
|
+
return cons.expression ? `return ${cons.expression};` : "return;";
|
|
619
|
+
case "WhileConsequence": {
|
|
620
|
+
const body = cons.body.map((c) => `${indent} ${generateConsequence(c, indent + " ")}`).join("\n");
|
|
621
|
+
return `while (${cons.condition}) {
|
|
622
|
+
${body}
|
|
623
|
+
${indent}}`;
|
|
624
|
+
}
|
|
625
|
+
case "ForEachConsequence": {
|
|
626
|
+
const body = cons.body.map((c) => `${indent} ${generateConsequence(c, indent + " ")}`).join("\n");
|
|
627
|
+
return `for (${cons.typeName} ${cons.varName} : ${cons.collection}) {
|
|
628
|
+
${body}
|
|
629
|
+
${indent}}`;
|
|
630
|
+
}
|
|
631
|
+
case "ForConsequence": {
|
|
632
|
+
const body = cons.body.map((c) => `${indent} ${generateConsequence(c, indent + " ")}`).join("\n");
|
|
633
|
+
return `for (${cons.init}; ${cons.condition}; ${cons.update}) {
|
|
634
|
+
${body}
|
|
635
|
+
${indent}}`;
|
|
636
|
+
}
|
|
637
|
+
case "VarDeclConsequence":
|
|
638
|
+
return `${cons.typeName} ${cons.name} = ${cons.value};`;
|
|
639
|
+
case "MethodCallConsequence":
|
|
640
|
+
return `${cons.object}.${cons.method}(${cons.args});`;
|
|
641
|
+
case "SwitchConsequence": {
|
|
642
|
+
const caseLines = cons.cases.map((c) => {
|
|
643
|
+
const body = c.body.map((b) => `${indent} ${generateConsequence(b, indent + " ")}`).join("\n");
|
|
644
|
+
return `${indent} case ${c.value}:
|
|
645
|
+
${body}
|
|
646
|
+
${indent} break;`;
|
|
647
|
+
});
|
|
648
|
+
if (cons.default && cons.default.length > 0) {
|
|
649
|
+
const defBody = cons.default.map((b) => `${indent} ${generateConsequence(b, indent + " ")}`).join("\n");
|
|
650
|
+
caseLines.push(`${indent} default:
|
|
651
|
+
${defBody}`);
|
|
652
|
+
}
|
|
653
|
+
return `switch (${cons.expression}) {
|
|
654
|
+
${caseLines.join("\n")}
|
|
655
|
+
${indent}}`;
|
|
656
|
+
}
|
|
657
|
+
case "IfConsequence": {
|
|
658
|
+
const thenLines = cons.then.map((c) => `${indent} ${generateConsequence(c, indent + " ")}`).join("\n");
|
|
659
|
+
if (cons.else && cons.else.length > 0) {
|
|
660
|
+
const elseLines = cons.else.map((c) => `${indent} ${generateConsequence(c, indent + " ")}`).join("\n");
|
|
661
|
+
return `if (${cons.condition}) {
|
|
662
|
+
${thenLines}
|
|
663
|
+
${indent}} else {
|
|
664
|
+
${elseLines}
|
|
665
|
+
${indent}}`;
|
|
666
|
+
}
|
|
667
|
+
return `if (${cons.condition}) {
|
|
668
|
+
${thenLines}
|
|
669
|
+
${indent}}`;
|
|
670
|
+
}
|
|
617
671
|
}
|
|
618
672
|
}
|
|
673
|
+
function generateDeclaration(decl) {
|
|
674
|
+
const attrs = decl.attributes.map((a) => ` ${a.name} : ${a.type}`).join("\n");
|
|
675
|
+
return `declare ${decl.className}${attrs ? "\n" + attrs + "\n" : "\n"}end`;
|
|
676
|
+
}
|
|
677
|
+
function generateFunction(fn, indent = " ") {
|
|
678
|
+
const body = fn.body.map((c) => `${indent}${generateConsequence(c, indent)}`).join("\n");
|
|
679
|
+
return `function ${fn.returnType} ${fn.name}(${fn.params}) {
|
|
680
|
+
${body}
|
|
681
|
+
}`;
|
|
682
|
+
}
|
|
619
683
|
function generateRule(rule) {
|
|
620
684
|
const lines = [`rule "${rule.name}"`];
|
|
621
685
|
if (rule.salience !== void 0) lines.push(` salience ${rule.salience}`);
|
|
@@ -637,6 +701,10 @@ var MetaToDRLTransformer = {
|
|
|
637
701
|
sections.push(file.imports.map((i) => `import ${i};`).join("\n"));
|
|
638
702
|
if (file.globals.length > 0)
|
|
639
703
|
sections.push(file.globals.map((g) => `global ${g.type} ${g.name};`).join("\n"));
|
|
704
|
+
if (file.declarations && file.declarations.length > 0)
|
|
705
|
+
sections.push(file.declarations.map((d) => generateDeclaration(d)).join("\n\n"));
|
|
706
|
+
if (file.functions && file.functions.length > 0)
|
|
707
|
+
sections.push(file.functions.map((fn) => generateFunction(fn)).join("\n\n"));
|
|
640
708
|
sections.push(file.rules.map(generateRule).join("\n\n"));
|
|
641
709
|
return sections.join("\n\n");
|
|
642
710
|
},
|
|
@@ -754,24 +822,54 @@ function parseGlobals(drl) {
|
|
|
754
822
|
}
|
|
755
823
|
function extractRuleBlocks(drl) {
|
|
756
824
|
const blocks = [];
|
|
757
|
-
const re = /\brule\s+"[^"]*"[\s\S]*?\bend\b/g;
|
|
825
|
+
const re = /\brule\s+(?:"[^"]*"|'[^']*')[\s\S]*?\bend\b/g;
|
|
758
826
|
let m;
|
|
759
827
|
while ((m = re.exec(drl)) !== null) blocks.push(m[0]);
|
|
760
828
|
return blocks;
|
|
761
829
|
}
|
|
830
|
+
function parseFunctions(drl) {
|
|
831
|
+
const results = [];
|
|
832
|
+
const re = /\bfunction\s+([\w<>?,\s\[\]]+?)\s+(\w+)\s*\(([^)]*)\)\s*\{([^{}]*(?:\{[^{}]*\}[^{}]*)*)\}/g;
|
|
833
|
+
let m;
|
|
834
|
+
while ((m = re.exec(drl)) !== null) {
|
|
835
|
+
results.push({
|
|
836
|
+
returnType: m[1].trim(),
|
|
837
|
+
name: m[2].trim(),
|
|
838
|
+
params: m[3].trim(),
|
|
839
|
+
body: parseConsequences(m[4].trim())
|
|
840
|
+
});
|
|
841
|
+
}
|
|
842
|
+
return results;
|
|
843
|
+
}
|
|
844
|
+
function parseDeclarations(drl) {
|
|
845
|
+
const results = [];
|
|
846
|
+
const re = /\bdeclare\s+(\w+)\s*([\s\S]*?)\bend\b/g;
|
|
847
|
+
let m;
|
|
848
|
+
while ((m = re.exec(drl)) !== null) {
|
|
849
|
+
const className = m[1].trim();
|
|
850
|
+
const attributes = [];
|
|
851
|
+
const attrRe = /^\s*(\w+)\s*:\s*(\S+)/gm;
|
|
852
|
+
let a;
|
|
853
|
+
while ((a = attrRe.exec(m[2])) !== null) {
|
|
854
|
+
attributes.push({ name: a[1].trim(), type: a[2].trim() });
|
|
855
|
+
}
|
|
856
|
+
results.push({ className, attributes });
|
|
857
|
+
}
|
|
858
|
+
return results;
|
|
859
|
+
}
|
|
762
860
|
function parseRuleName(block) {
|
|
763
|
-
const m = block.match(/\brule\s+"([^"]+)"/);
|
|
764
|
-
return m ? m[1] : "unknown";
|
|
861
|
+
const m = block.match(/\brule\s+(?:"([^"]+)"|'([^']+)')/);
|
|
862
|
+
return m ? m[1] ?? m[2] : "unknown";
|
|
765
863
|
}
|
|
766
864
|
function parseRuleAttributes(block) {
|
|
767
865
|
const attrs = {};
|
|
768
|
-
const m = block.match(/\brule\s+"[^"]+"\s*([\s\S]*?)\bwhen\b/);
|
|
866
|
+
const m = block.match(/\brule\s+(?:"[^"]+"|'[^']+')\s*([\s\S]*?)\bwhen\b/);
|
|
769
867
|
if (!m) return attrs;
|
|
770
868
|
const attr = m[1];
|
|
771
869
|
const salience = attr.match(/\bsalience\s+(-?\d+)/);
|
|
772
870
|
if (salience) attrs.salience = parseInt(salience[1], 10);
|
|
773
|
-
if (
|
|
774
|
-
if (
|
|
871
|
+
if (!/\bno-loop\s+false\b/.test(attr) && /\bno-loop\b/.test(attr)) attrs.noLoop = true;
|
|
872
|
+
if (!/\block-on-active\s+false\b/.test(attr) && /\block-on-active\b/.test(attr)) attrs.lockOnActive = true;
|
|
775
873
|
const ag = attr.match(/\bagenda-group\s+"([^"]+)"/);
|
|
776
874
|
if (ag) attrs.agendaGroup = ag[1];
|
|
777
875
|
const rfg = attr.match(/\bruleflow-group\s+"([^"]+)"/);
|
|
@@ -937,6 +1035,31 @@ function parseFrom(text, fromIdx) {
|
|
|
937
1035
|
expression: text.slice(fromIdx + " from ".length).trim()
|
|
938
1036
|
};
|
|
939
1037
|
}
|
|
1038
|
+
function parseSwitchBody(body) {
|
|
1039
|
+
const cases = [];
|
|
1040
|
+
let defaultBody;
|
|
1041
|
+
const markers = [];
|
|
1042
|
+
const caseRe = /\bcase\s+([^:]+):/g;
|
|
1043
|
+
const defRe = /\bdefault\s*:/g;
|
|
1044
|
+
let m;
|
|
1045
|
+
while ((m = caseRe.exec(body)) !== null)
|
|
1046
|
+
markers.push({ index: m.index, headerLen: m[0].length, type: "case", value: m[1].trim() });
|
|
1047
|
+
while ((m = defRe.exec(body)) !== null)
|
|
1048
|
+
markers.push({ index: m.index, headerLen: m[0].length, type: "default" });
|
|
1049
|
+
markers.sort((a, b) => a.index - b.index);
|
|
1050
|
+
for (let i = 0; i < markers.length; i++) {
|
|
1051
|
+
const marker = markers[i];
|
|
1052
|
+
const contentStart = marker.index + marker.headerLen;
|
|
1053
|
+
const contentEnd = i + 1 < markers.length ? markers[i + 1].index : body.length;
|
|
1054
|
+
const raw = body.slice(contentStart, contentEnd).trim();
|
|
1055
|
+
const content = raw.replace(/\s*\bbreak\s*;\s*$/, "").trim();
|
|
1056
|
+
if (marker.type === "case")
|
|
1057
|
+
cases.push({ kind: "CaseConsequence", value: marker.value, body: parseConsequences(content) });
|
|
1058
|
+
else
|
|
1059
|
+
defaultBody = parseConsequences(content);
|
|
1060
|
+
}
|
|
1061
|
+
return { cases, ...defaultBody !== void 0 && { default: defaultBody } };
|
|
1062
|
+
}
|
|
940
1063
|
function parseConsequences(then) {
|
|
941
1064
|
const consequences = [];
|
|
942
1065
|
let remaining = then.trim();
|
|
@@ -951,6 +1074,65 @@ function parseConsequences(then) {
|
|
|
951
1074
|
function parseNextConsequence(text) {
|
|
952
1075
|
const t = text.trim();
|
|
953
1076
|
if (!t) return null;
|
|
1077
|
+
if (/^while\s*\(/.test(t)) {
|
|
1078
|
+
const condition = extractBalanced(t, "(", ")");
|
|
1079
|
+
const afterCond = t.slice(t.indexOf("(") + condition.length + 2).trim();
|
|
1080
|
+
const body = extractBalanced(afterCond, "{", "}");
|
|
1081
|
+
const endIdx = afterCond.indexOf("{") + body.length + 2;
|
|
1082
|
+
return {
|
|
1083
|
+
consequence: { kind: "WhileConsequence", condition: condition.trim(), body: parseConsequences(body) },
|
|
1084
|
+
rest: afterCond.slice(endIdx)
|
|
1085
|
+
};
|
|
1086
|
+
}
|
|
1087
|
+
if (/^for\s*\(/.test(t)) {
|
|
1088
|
+
const header = extractBalanced(t, "(", ")");
|
|
1089
|
+
const afterHeader = t.slice(t.indexOf("(") + header.length + 2).trim();
|
|
1090
|
+
const body = extractBalanced(afterHeader, "{", "}");
|
|
1091
|
+
const endIdx = afterHeader.indexOf("{") + body.length + 2;
|
|
1092
|
+
const colonIdx = indexAtDepth0(header, ":");
|
|
1093
|
+
if (colonIdx !== -1 && indexAtDepth0(header, ";") === -1) {
|
|
1094
|
+
const parts = header.slice(0, colonIdx).trim().split(/\s+/);
|
|
1095
|
+
const varName = parts.pop();
|
|
1096
|
+
const typeName = parts.join(" ");
|
|
1097
|
+
return {
|
|
1098
|
+
consequence: { kind: "ForEachConsequence", typeName, varName, collection: header.slice(colonIdx + 1).trim(), body: parseConsequences(body) },
|
|
1099
|
+
rest: afterHeader.slice(endIdx)
|
|
1100
|
+
};
|
|
1101
|
+
} else {
|
|
1102
|
+
const parts = splitAtDepth0(header, ";");
|
|
1103
|
+
return {
|
|
1104
|
+
consequence: { kind: "ForConsequence", init: (parts[0] ?? "").trim(), condition: (parts[1] ?? "").trim(), update: (parts[2] ?? "").trim(), body: parseConsequences(body) },
|
|
1105
|
+
rest: afterHeader.slice(endIdx)
|
|
1106
|
+
};
|
|
1107
|
+
}
|
|
1108
|
+
}
|
|
1109
|
+
if (/^switch\s*\(/.test(t)) {
|
|
1110
|
+
const expression = extractBalanced(t, "(", ")");
|
|
1111
|
+
const afterExpr = t.slice(t.indexOf("(") + expression.length + 2).trim();
|
|
1112
|
+
const switchBody = extractBalanced(afterExpr, "{", "}");
|
|
1113
|
+
const endIdx = afterExpr.indexOf("{") + switchBody.length + 2;
|
|
1114
|
+
return {
|
|
1115
|
+
consequence: { kind: "SwitchConsequence", expression: expression.trim(), ...parseSwitchBody(switchBody) },
|
|
1116
|
+
rest: afterExpr.slice(endIdx)
|
|
1117
|
+
};
|
|
1118
|
+
}
|
|
1119
|
+
if (/^if\s*\(/.test(t)) {
|
|
1120
|
+
const condition = extractBalanced(t, "(", ")");
|
|
1121
|
+
const afterCond = t.slice(t.indexOf("(") + condition.length + 2).trim();
|
|
1122
|
+
const thenBlock = extractBalanced(afterCond, "{", "}");
|
|
1123
|
+
const thenConsequences = parseConsequences(thenBlock);
|
|
1124
|
+
let afterThen = afterCond.slice(afterCond.indexOf("{") + thenBlock.length + 2).trim();
|
|
1125
|
+
let elseConsequences;
|
|
1126
|
+
if (/^else\s*\{/.test(afterThen)) {
|
|
1127
|
+
const elseBlock = extractBalanced(afterThen, "{", "}");
|
|
1128
|
+
elseConsequences = parseConsequences(elseBlock);
|
|
1129
|
+
afterThen = afterThen.slice(afterThen.indexOf("{") + elseBlock.length + 2).trim();
|
|
1130
|
+
}
|
|
1131
|
+
return {
|
|
1132
|
+
consequence: { kind: "IfConsequence", condition: condition.trim(), then: thenConsequences, ...elseConsequences && { else: elseConsequences } },
|
|
1133
|
+
rest: afterThen
|
|
1134
|
+
};
|
|
1135
|
+
}
|
|
954
1136
|
if (/^modify\s*\(/.test(t)) {
|
|
955
1137
|
const m = t.match(/^modify\s*\(\s*(\$\w+)\s*\)/);
|
|
956
1138
|
if (m) {
|
|
@@ -973,6 +1155,14 @@ function parseNextConsequence(text) {
|
|
|
973
1155
|
const rest = t.slice(t.indexOf("(") + inner.length + 2).replace(/^\s*;/, "");
|
|
974
1156
|
return { consequence: { kind: "RetractConsequence", binding: inner.trim() }, rest };
|
|
975
1157
|
}
|
|
1158
|
+
if (/^return\b/.test(t)) {
|
|
1159
|
+
const semiIdx2 = indexAtDepth0(t, ";");
|
|
1160
|
+
const expression = t.slice("return".length, semiIdx2 !== -1 ? semiIdx2 : void 0).trim();
|
|
1161
|
+
return {
|
|
1162
|
+
consequence: { kind: "ReturnConsequence", expression },
|
|
1163
|
+
rest: semiIdx2 !== -1 ? t.slice(semiIdx2 + 1) : ""
|
|
1164
|
+
};
|
|
1165
|
+
}
|
|
976
1166
|
const semiIdx = indexAtDepth0(t, ";");
|
|
977
1167
|
if (semiIdx !== -1)
|
|
978
1168
|
return { consequence: { kind: "RawConsequence", code: t.slice(0, semiIdx).trim() }, rest: t.slice(semiIdx + 1) };
|
|
@@ -991,8 +1181,10 @@ var DRLToMetaTransformer = {
|
|
|
991
1181
|
const clean = stripComments(drl);
|
|
992
1182
|
return {
|
|
993
1183
|
name: "parsed",
|
|
994
|
-
imports: parseImports(clean),
|
|
1184
|
+
imports: [...new Set(parseImports(clean))],
|
|
995
1185
|
globals: parseGlobals(clean),
|
|
1186
|
+
declarations: parseDeclarations(clean),
|
|
1187
|
+
functions: parseFunctions(clean),
|
|
996
1188
|
rules: extractRuleBlocks(clean).map((block) => DRLToMetaTransformer.parseRule(block))
|
|
997
1189
|
};
|
|
998
1190
|
},
|