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