source: node_modules/jsonify/lib/parse.js@ d24f17c

main
Last change on this file since d24f17c was d24f17c, checked in by Aleksandar Panovski <apano77@…>, 15 months ago

Initial commit

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