1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 | "use strict";
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 | module.exports = function(tokens) {
|
14 | var api = {},
|
15 | starts = Object.create(null),
|
16 | ends = Object.create(null),
|
17 | index, length, range;
|
18 |
|
19 | |
20 |
|
21 |
|
22 |
|
23 |
|
24 |
|
25 | function get(start, end) {
|
26 | var result = [],
|
27 | i;
|
28 |
|
29 | for (i = Math.max(0, start); i < end && i < length; i++) {
|
30 | result.push(tokens[i]);
|
31 | }
|
32 |
|
33 | return result;
|
34 | }
|
35 |
|
36 | |
37 |
|
38 |
|
39 |
|
40 |
|
41 |
|
42 |
|
43 | function lastTokenIndex(node) {
|
44 | var end = node.range[1],
|
45 | cursor = ends[end];
|
46 |
|
47 |
|
48 |
|
49 | if (typeof cursor === "undefined") {
|
50 | cursor = starts[end] - 1;
|
51 | }
|
52 |
|
53 |
|
54 |
|
55 | if (isNaN(cursor)) {
|
56 | cursor = length - 1;
|
57 | }
|
58 |
|
59 | return cursor;
|
60 | }
|
61 |
|
62 |
|
63 | for (index = 0, length = tokens.length; index < length; index++) {
|
64 | range = tokens[index].range;
|
65 | starts[range[0]] = index;
|
66 | ends[range[1]] = index;
|
67 | }
|
68 |
|
69 | |
70 |
|
71 |
|
72 |
|
73 |
|
74 |
|
75 |
|
76 |
|
77 | api.getTokensBefore = function(node, beforeCount) {
|
78 | var first = starts[node.range[0]];
|
79 | return get(first - (beforeCount || 0), first);
|
80 | };
|
81 |
|
82 | /**
|
83 | * Gets the token that precedes a given node or token in the token stream.
|
84 | * @param {(ASTNode|Token)} node The AST node or token.
|
85 | * @param {int} [skip=0] A number of tokens to skip before the given node or
|
86 | * token.
|
87 | * @returns {Token} An object representing the token.
|
88 | */
|
89 | api.getTokenBefore = function(node, skip) {
|
90 | return tokens[starts[node.range[0]] - (skip || 0) - 1];
|
91 | };
|
92 |
|
93 | |
94 |
|
95 |
|
96 |
|
97 |
|
98 |
|
99 |
|
100 |
|
101 | api.getTokensAfter = function(node, afterCount) {
|
102 | var start = lastTokenIndex(node) + 1;
|
103 | return get(start, start + (afterCount || 0));
|
104 | };
|
105 |
|
106 | /**
|
107 | * Gets the token that follows a given node or token in the token stream.
|
108 | * @param {(ASTNode|Token)} node The AST node or token.
|
109 | * @param {int} [skip=0] A number of tokens to skip after the given node or
|
110 | * token.
|
111 | * @returns {Token} An object representing the token.
|
112 | */
|
113 | api.getTokenAfter = function(node, skip) {
|
114 | return tokens[lastTokenIndex(node) + (skip || 0) + 1];
|
115 | };
|
116 |
|
117 | |
118 |
|
119 |
|
120 |
|
121 |
|
122 |
|
123 |
|
124 | api.getTokens = function(node, beforeCount, afterCount) {
|
125 | return get(
|
126 | starts[node.range[0]] - (beforeCount || 0),
|
127 | lastTokenIndex(node) + (afterCount || 0) + 1
|
128 | );
|
129 | };
|
130 |
|
131 | /**
|
132 | * Gets the first `count` tokens of the given node's token stream.
|
133 | * @param {ASTNode} node The AST node.
|
134 | * @param {int} [count=0] The number of tokens of the node to retrieve.
|
135 | * @returns {Token[]} Array of objects representing tokens.
|
136 | */
|
137 | api.getFirstTokens = function(node, count) {
|
138 | var first = starts[node.range[0]];
|
139 | return get(
|
140 | first,
|
141 | Math.min(lastTokenIndex(node) + 1, first + (count || 0))
|
142 | );
|
143 | };
|
144 |
|
145 | /**
|
146 | * Gets the first token of the given node's token stream.
|
147 | * @param {ASTNode} node The AST node.
|
148 | * @param {int} [skip=0] A number of tokens to skip.
|
149 | * @returns {Token} An object representing the token.
|
150 | */
|
151 | api.getFirstToken = function(node, skip) {
|
152 | return tokens[starts[node.range[0]] + (skip || 0)];
|
153 | };
|
154 |
|
155 | |
156 |
|
157 |
|
158 |
|
159 |
|
160 |
|
161 | api.getLastTokens = function(node, count) {
|
162 | var last = lastTokenIndex(node) + 1;
|
163 | return get(Math.max(starts[node.range[0]], last - (count || 0)), last);
|
164 | };
|
165 |
|
166 | /**
|
167 | * Gets the last token of the given node's token stream.
|
168 | * @param {ASTNode} node The AST node.
|
169 | * @param {int} [skip=0] A number of tokens to skip.
|
170 | * @returns {Token} An object representing the token.
|
171 | */
|
172 | api.getLastToken = function(node, skip) {
|
173 | return tokens[lastTokenIndex(node) - (skip || 0)];
|
174 | };
|
175 |
|
176 | |
177 |
|
178 |
|
179 |
|
180 |
|
181 |
|
182 |
|
183 | api.getTokensBetween = function(left, right, padding) {
|
184 | padding = padding || 0;
|
185 | return get(
|
186 | lastTokenIndex(left) + 1 - padding,
|
187 | starts[right.range[0]] + padding
|
188 | );
|
189 | };
|
190 |
|
191 | /**
|
192 | * Gets the token starting at the specified index.
|
193 | * @param {int} startIndex Index of the start of the token's range.
|
194 | * @returns {Token} The token starting at index, or null if no such token.
|
195 | */
|
196 | api.getTokenByRangeStart = function(startIndex) {
|
197 | return (tokens[starts[startIndex]] || null);
|
198 | };
|
199 |
|
200 | return api;
|
201 | };
|