forked from 0xABAD/behavior_tree
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathparseBehaviorTree.js
More file actions
95 lines (91 loc) · 2.56 KB
/
parseBehaviorTree.js
File metadata and controls
95 lines (91 loc) · 2.56 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
function expect(what, have) {
return `Expecting '${what}', have '${have}'`;
}
function ParseException(message, lineNum) {
const error = new Error(message);
error.lineNum = lineNum;
return error;
}
function parseBehaviorTreeFromText(buf) {
/** @type {Node[]} nodes in the current tree branch */
let nodes = [null];
let indent = 0;
function pushNode(node) {
if (indent === 0 && nodes[indent]) {
return `More than one root node or node '${node.name}' has wrong indentation.`;
}
if (indent > 0) {
let parent = nodes[indent - 1];
if (!parent) {
return `${node.name} node has no parent (wrong indentation level)`;
}
if (parent.children) {
parent.children.push(node);
nodes[indent] = node;
} else {
return `${parent.kind} node can't have child nodes`;
}
} else {
nodes[indent] = node;
}
indent++; // nested child on the same line should be indented
return null; // no error to be reported
};
const lines = buf.split('\n');
let lineNum = 0;
for (let line of lines) {
let not = false;
indent = 0;
lineNum++;
for (let part of line.split(' ')) {
if (part.length === 0) {
continue;
}
let pos = 0;
let err = null;
while (part[pos] === '|') {
indent++;
pos++;
}
while (part[pos] === '!') {
not = !not;
pos++;
}
if (pos >= part.length) {
continue;
}
switch (part[pos]) {
case '-':
if (part[pos + 1] != '>') {
throw ParseException(expect('->', part[pos + 1]), lineNum);
}
err = pushNode(new Sequence());
break;
case '?':
err = pushNode(new Fallback());
break;
case '=':
let number = parseInt(part.substring(pos + 1));
if (isNaN(number)) {
throw ParseException(expect('number', part.substring(pos + 1)), lineNum);
}
err = pushNode(new Parallel(number));
break;
case '[':
let actionName = part.substring(pos + 1, part.length - 1);
err = pushNode(new Action(actionName));
break;
case '(':
let conditionName = part.substring(pos + 1, part.length - 1);
err = pushNode(new Condition(conditionName, not));
break;
default:
throw ParseException(`Expecting '|', '-', '!', '[', or '(' but have '${part[pos]}'`, lineNum);
}
if (err) {
throw ParseException(err, lineNum);
}
}
}
return nodes[0];
}