-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathevaluator.ts
More file actions
104 lines (84 loc) · 2.98 KB
/
evaluator.ts
File metadata and controls
104 lines (84 loc) · 2.98 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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
import { Edge, Graph, Vertex } from "../simulator/graph";
import * as ast from "./ast";
export class Evaluator {
constructor(private readonly definition?: ast.Definition) {}
eval(): Array<Graph> {
if (!this.definition || this.definition.graphs.length == 0) {
return [];
}
// TODO: We probably need some identifier to distinguish graphs
// from each other.
const graphs: Array<Graph> = [];
for (const graph of this.definition.graphs) {
const evaluatedGraph: Graph = { edges: {}, vertices: {} };
this.evalGraphStatement(graph, evaluatedGraph);
graphs.push(evaluatedGraph);
}
return graphs;
}
private evalGraphStatement(graphStatement: ast.GraphStatement, graph: Graph) {
for (const stmt of graphStatement.statements) {
if (stmt instanceof ast.NodeStatement) {
this.evalNodeStatement(stmt, graph);
}
if (stmt instanceof ast.EdgeStatement) {
this.evalEdgeStatement(stmt, graph);
}
}
}
private evalNodeStatement(nodeStatement: ast.NodeStatement, graph: Graph) {
// TODO: Do something cool with attributes
const attributes = this.evalAttributesList(nodeStatement.attributesList);
graph.vertices[nodeStatement.id.value] = new Vertex(
nodeStatement.id.value,
attributes["cost"] && typeof attributes["cost"] === "number" ? attributes["cost"] : 0
);
}
private evalEdgeStatement(stmt: ast.EdgeStatement, graph: Graph) {
const leftId = stmt.left.value;
if (!graph.vertices[leftId]) {
graph.vertices[leftId] = new Vertex(leftId, 0);
}
const rightId = stmt.right.value;
if (!graph.vertices[rightId]) {
graph.vertices[rightId] = new Vertex(rightId, 0);
}
const attributesList = this.evalAttributesList(stmt.attributeList);
const isDirected = stmt.edgeType === "->";
const edgeId = crypto.randomUUID();
const edge = new Edge(
edgeId,
leftId,
rightId,
attributesList["cost"] && typeof attributesList["cost"] === "number"
? attributesList["cost"]
: null,
attributesList["name"] && typeof attributesList["name"] === "string"
? attributesList["name"]
: null,
isDirected
);
const leftVertex = graph.vertices[leftId];
const rightVertex = graph.vertices[rightId];
leftVertex.outs.push(edgeId);
rightVertex.ins.push(edgeId);
if (!isDirected) {
leftVertex.ins.push(edgeId);
rightVertex.outs.push(edgeId);
}
graph.edges[edgeId] = edge;
}
private evalAttributesList(
stmts: Array<ast.AttributeStatement>
): Record<string, string | number> {
const attributes: Record<string, string | number> = {};
for (const attrStmt of stmts) {
// This a bit hacky, but it works as value can't be
// anything other than number at the moment.
const key = attrStmt.key.value;
const value = (attrStmt.value as ast.Identifier | ast.NumberLiteral).value;
attributes[key] = value;
}
return attributes;
}
}