Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
80713 views
1
import Exception from "../exception";
2
import AST from "./ast";
3
4
function Visitor() {
5
this.parents = [];
6
}
7
8
Visitor.prototype = {
9
constructor: Visitor,
10
mutating: false,
11
12
// Visits a given value. If mutating, will replace the value if necessary.
13
acceptKey: function(node, name) {
14
var value = this.accept(node[name]);
15
if (this.mutating) {
16
// Hacky sanity check:
17
if (value && (!value.type || !AST[value.type])) {
18
throw new Exception('Unexpected node type "' + value.type + '" found when accepting ' + name + ' on ' + node.type);
19
}
20
node[name] = value;
21
}
22
},
23
24
// Performs an accept operation with added sanity check to ensure
25
// required keys are not removed.
26
acceptRequired: function(node, name) {
27
this.acceptKey(node, name);
28
29
if (!node[name]) {
30
throw new Exception(node.type + ' requires ' + name);
31
}
32
},
33
34
// Traverses a given array. If mutating, empty respnses will be removed
35
// for child elements.
36
acceptArray: function(array) {
37
for (var i = 0, l = array.length; i < l; i++) {
38
this.acceptKey(array, i);
39
40
if (!array[i]) {
41
array.splice(i, 1);
42
i--;
43
l--;
44
}
45
}
46
},
47
48
accept: function(object) {
49
if (!object) {
50
return;
51
}
52
53
if (this.current) {
54
this.parents.unshift(this.current);
55
}
56
this.current = object;
57
58
var ret = this[object.type](object);
59
60
this.current = this.parents.shift();
61
62
if (!this.mutating || ret) {
63
return ret;
64
} else if (ret !== false) {
65
return object;
66
}
67
},
68
69
Program: function(program) {
70
this.acceptArray(program.body);
71
},
72
73
MustacheStatement: function(mustache) {
74
this.acceptRequired(mustache, 'path');
75
this.acceptArray(mustache.params);
76
this.acceptKey(mustache, 'hash');
77
},
78
79
BlockStatement: function(block) {
80
this.acceptRequired(block, 'path');
81
this.acceptArray(block.params);
82
this.acceptKey(block, 'hash');
83
84
this.acceptKey(block, 'program');
85
this.acceptKey(block, 'inverse');
86
},
87
88
PartialStatement: function(partial) {
89
this.acceptRequired(partial, 'name');
90
this.acceptArray(partial.params);
91
this.acceptKey(partial, 'hash');
92
},
93
94
ContentStatement: function(/* content */) {},
95
CommentStatement: function(/* comment */) {},
96
97
SubExpression: function(sexpr) {
98
this.acceptRequired(sexpr, 'path');
99
this.acceptArray(sexpr.params);
100
this.acceptKey(sexpr, 'hash');
101
},
102
PartialExpression: function(partial) {
103
this.acceptRequired(partial, 'name');
104
this.acceptArray(partial.params);
105
this.acceptKey(partial, 'hash');
106
},
107
108
PathExpression: function(/* path */) {},
109
110
StringLiteral: function(/* string */) {},
111
NumberLiteral: function(/* number */) {},
112
BooleanLiteral: function(/* bool */) {},
113
114
Hash: function(hash) {
115
this.acceptArray(hash.pairs);
116
},
117
HashPair: function(pair) {
118
this.acceptRequired(pair, 'value');
119
}
120
};
121
122
export default Visitor;
123
124