-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathconceptGraph.js
More file actions
85 lines (74 loc) · 2.26 KB
/
conceptGraph.js
File metadata and controls
85 lines (74 loc) · 2.26 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
// conceptGraph.js
const fs = require("fs");
/**
* Parse a simple DSL with generic pattern:
* A <Entity> <statement> <Entity>
* AN <Entity> <statement> <Entity>
*
* Where:
* - Entities start with a capital letter (e.g., DataDomain, UseCase)
* - Statements are lowercase with spaces (e.g., has many, is implemented by)
*
* Examples:
* A DataDomain has many UseCases
* A UseCase has DataConsumerRequirements
* An Assessment produces many ScoreCards
* A LogicalRule is implemented by many TechnicalRules
*
* Returns:
* {
* nodes: [{ id, label }],
* edges: [{ source, target, label }]
* }
*/
function parseConceptDsl(text) {
const nodesMap = new Map(); // id -> { id, label }
const edges = [];
function ensureNode(name) {
const id = name.trim();
if (!nodesMap.has(id)) {
nodesMap.set(id, { id, label: id });
}
return id;
}
function addEdge(sourceName, targetName, label) {
const source = ensureNode(sourceName);
const target = ensureNode(targetName);
edges.push({ source, target, label });
}
const lines = text
.split(/\r?\n/)
.map((l) => l.trim())
.filter((l) => l && !l.startsWith("//") && !l.startsWith("#"));
for (const line of lines) {
// Generic pattern: A|AN <Entity> <statement> <Entity>
// Entity: starts with capital letter, followed by alphanumeric characters
// Statement: lowercase words with spaces between entities
const pattern = /^(?:A|An)\s+([A-Z]\w+)\s+(.+?)\s+([A-Z]\w+)$/;
const match = pattern.exec(line);
if (match) {
const [, sourceEntity, statement, targetEntity] = match;
// Normalize the statement (trim and convert to lowercase)
const normalizedStatement = statement.trim().toLowerCase();
addEdge(sourceEntity, targetEntity, normalizedStatement);
} else {
// If pattern doesn't match, warn but don't fail
console.warn("[conceptGraph] Unrecognized line:", line);
}
}
return {
nodes: Array.from(nodesMap.values()),
edges,
};
}
/**
* Load a .concept file and parse into graph.
*/
function buildConceptGraphFromFile(filePath) {
const text = fs.readFileSync(filePath, "utf8");
return parseConceptDsl(text);
}
module.exports = {
parseConceptDsl,
buildConceptGraphFromFile,
};