-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathnode.js
More file actions
93 lines (78 loc) · 1.94 KB
/
node.js
File metadata and controls
93 lines (78 loc) · 1.94 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
const TokenType = require('./token-type');
class ExpNode {
constructor(op, left, right, literal) {
this.op = op;
this.left = left;
this.right = right;
this.literal = literal;
}
isLeaf() {
return this.op === TokenType.LEAF;
}
isAtomic() {
return (
this.isLeaf() || (this.op === TokenType.OP_NOT && this.left.isLeaf())
);
}
getLiteralValue() {
return this.literal;
}
static CreateAnd(left, right) {
return new ExpNode(TokenType.BINARY_AND, left, right);
}
static CreateNot(exp) {
return new ExpNode(TokenType.OP_NOT, exp);
}
static CreateOr(left, right) {
return new ExpNode(TokenType.BINARY_OR, left, right);
}
static CreateLiteral(lit) {
return new ExpNode(TokenType.LEAF, null, null, lit);
}
}
// 抽象语法树生成
const make = gen => {
const data = gen.next().value;
switch (data.type) {
case TokenType.LITERAL:
return ExpNode.CreateLiteral(data.value);
case TokenType.OP_NOT:
return ExpNode.CreateNot(make(gen));
case TokenType.BINARY_AND: {
const left = make(gen);
const right = make(gen);
return ExpNode.CreateAnd(left, right);
}
case TokenType.BINARY_OR: {
const left = make(gen);
const right = make(gen);
return ExpNode.CreateOr(left, right);
}
}
return null;
};
// 语法树求值
const nodeEvaluator = (tree, literalEvaluator) => {
if (tree.isLeaf()) {
return literalEvaluator(tree.getLiteralValue());
}
if (tree.op === TokenType.OP_NOT) {
return !nodeEvaluator(tree.left, literalEvaluator);
}
if (tree.op === TokenType.BINARY_OR) {
return (
nodeEvaluator(tree.left, literalEvaluator) ||
nodeEvaluator(tree.right, literalEvaluator)
);
}
if (tree.op === TokenType.BINARY_AND) {
return (
nodeEvaluator(tree.left, literalEvaluator) &&
nodeEvaluator(tree.right, literalEvaluator)
);
}
};
module.exports = {
make,
nodeEvaluator
};