]> git.r.bdr.sh - rbdr/dotfiles/blob - atom/packages/pretty-json/node_modules/json-stable-stringify/node_modules/jsonify/lib/parse.js
30e2f014363514f3d0f23bc81f1abde6bde44b90
[rbdr/dotfiles] / atom / packages / pretty-json / node_modules / json-stable-stringify / node_modules / jsonify / lib / parse.js
1 var at, // The index of the current character
2 ch, // The current character
3 escapee = {
4 '"': '"',
5 '\\': '\\',
6 '/': '/',
7 b: '\b',
8 f: '\f',
9 n: '\n',
10 r: '\r',
11 t: '\t'
12 },
13 text,
14
15 error = function (m) {
16 // Call error when something is wrong.
17 throw {
18 name: 'SyntaxError',
19 message: m,
20 at: at,
21 text: text
22 };
23 },
24
25 next = function (c) {
26 // If a c parameter is provided, verify that it matches the current character.
27 if (c && c !== ch) {
28 error("Expected '" + c + "' instead of '" + ch + "'");
29 }
30
31 // Get the next character. When there are no more characters,
32 // return the empty string.
33
34 ch = text.charAt(at);
35 at += 1;
36 return ch;
37 },
38
39 number = function () {
40 // Parse a number value.
41 var number,
42 string = '';
43
44 if (ch === '-') {
45 string = '-';
46 next('-');
47 }
48 while (ch >= '0' && ch <= '9') {
49 string += ch;
50 next();
51 }
52 if (ch === '.') {
53 string += '.';
54 while (next() && ch >= '0' && ch <= '9') {
55 string += ch;
56 }
57 }
58 if (ch === 'e' || ch === 'E') {
59 string += ch;
60 next();
61 if (ch === '-' || ch === '+') {
62 string += ch;
63 next();
64 }
65 while (ch >= '0' && ch <= '9') {
66 string += ch;
67 next();
68 }
69 }
70 number = +string;
71 if (!isFinite(number)) {
72 error("Bad number");
73 } else {
74 return number;
75 }
76 },
77
78 string = function () {
79 // Parse a string value.
80 var hex,
81 i,
82 string = '',
83 uffff;
84
85 // When parsing for string values, we must look for " and \ characters.
86 if (ch === '"') {
87 while (next()) {
88 if (ch === '"') {
89 next();
90 return string;
91 } else if (ch === '\\') {
92 next();
93 if (ch === 'u') {
94 uffff = 0;
95 for (i = 0; i < 4; i += 1) {
96 hex = parseInt(next(), 16);
97 if (!isFinite(hex)) {
98 break;
99 }
100 uffff = uffff * 16 + hex;
101 }
102 string += String.fromCharCode(uffff);
103 } else if (typeof escapee[ch] === 'string') {
104 string += escapee[ch];
105 } else {
106 break;
107 }
108 } else {
109 string += ch;
110 }
111 }
112 }
113 error("Bad string");
114 },
115
116 white = function () {
117
118 // Skip whitespace.
119
120 while (ch && ch <= ' ') {
121 next();
122 }
123 },
124
125 word = function () {
126
127 // true, false, or null.
128
129 switch (ch) {
130 case 't':
131 next('t');
132 next('r');
133 next('u');
134 next('e');
135 return true;
136 case 'f':
137 next('f');
138 next('a');
139 next('l');
140 next('s');
141 next('e');
142 return false;
143 case 'n':
144 next('n');
145 next('u');
146 next('l');
147 next('l');
148 return null;
149 }
150 error("Unexpected '" + ch + "'");
151 },
152
153 value, // Place holder for the value function.
154
155 array = function () {
156
157 // Parse an array value.
158
159 var array = [];
160
161 if (ch === '[') {
162 next('[');
163 white();
164 if (ch === ']') {
165 next(']');
166 return array; // empty array
167 }
168 while (ch) {
169 array.push(value());
170 white();
171 if (ch === ']') {
172 next(']');
173 return array;
174 }
175 next(',');
176 white();
177 }
178 }
179 error("Bad array");
180 },
181
182 object = function () {
183
184 // Parse an object value.
185
186 var key,
187 object = {};
188
189 if (ch === '{') {
190 next('{');
191 white();
192 if (ch === '}') {
193 next('}');
194 return object; // empty object
195 }
196 while (ch) {
197 key = string();
198 white();
199 next(':');
200 if (Object.hasOwnProperty.call(object, key)) {
201 error('Duplicate key "' + key + '"');
202 }
203 object[key] = value();
204 white();
205 if (ch === '}') {
206 next('}');
207 return object;
208 }
209 next(',');
210 white();
211 }
212 }
213 error("Bad object");
214 };
215
216 value = function () {
217
218 // Parse a JSON value. It could be an object, an array, a string, a number,
219 // or a word.
220
221 white();
222 switch (ch) {
223 case '{':
224 return object();
225 case '[':
226 return array();
227 case '"':
228 return string();
229 case '-':
230 return number();
231 default:
232 return ch >= '0' && ch <= '9' ? number() : word();
233 }
234 };
235
236 // Return the json_parse function. It will have access to all of the above
237 // functions and variables.
238
239 module.exports = function (source, reviver) {
240 var result;
241
242 text = source;
243 at = 0;
244 ch = ' ';
245 result = value();
246 white();
247 if (ch) {
248 error("Syntax error");
249 }
250
251 // If there is a reviver function, we recursively walk the new structure,
252 // passing each name/value pair to the reviver function for possible
253 // transformation, starting with a temporary root object that holds the result
254 // in an empty key. If there is not a reviver function, we simply return the
255 // result.
256
257 return typeof reviver === 'function' ? (function walk(holder, key) {
258 var k, v, value = holder[key];
259 if (value && typeof value === 'object') {
260 for (k in value) {
261 if (Object.prototype.hasOwnProperty.call(value, k)) {
262 v = walk(value, k);
263 if (v !== undefined) {
264 value[k] = v;
265 } else {
266 delete value[k];
267 }
268 }
269 }
270 }
271 return reviver.call(holder, key, value);
272 }({'': result}, '')) : result;
273 };