1 | module.exports = (function() {
|
2 | |
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 | function peg$subclass(child, parent) {
|
9 | function ctor() { this.constructor = child; }
|
10 | ctor.prototype = parent.prototype;
|
11 | child.prototype = new ctor();
|
12 | }
|
13 |
|
14 | function SyntaxError(message, expected, found, offset, line, column) {
|
15 | this.message = message;
|
16 | this.expected = expected;
|
17 | this.found = found;
|
18 | this.offset = offset;
|
19 | this.line = line;
|
20 | this.column = column;
|
21 |
|
22 | this.name = "SyntaxError";
|
23 | }
|
24 |
|
25 | peg$subclass(SyntaxError, Error);
|
26 |
|
27 | function parse(input) {
|
28 | var options = arguments.length > 1 ? arguments[1] : {},
|
29 |
|
30 | peg$FAILED = {},
|
31 |
|
32 | peg$startRuleFunctions = { start: peg$parsestart },
|
33 | peg$startRuleFunction = peg$parsestart,
|
34 |
|
35 | peg$c0 = peg$FAILED,
|
36 | peg$c1 = null,
|
37 | peg$c2 = [],
|
38 | peg$c3 = function(l) {
|
39 | var lines = compact(l).map(function(line){
|
40 | if(lastChar(line) !== DEDENT_CHAR){
|
41 | line = line + TERM_CHAR
|
42 | }
|
43 | return line;
|
44 | });
|
45 | return lines.join('');
|
46 | },
|
47 | peg$c4 = function() { return },
|
48 | peg$c5 = void 0,
|
49 | peg$c6 = { type: "any", description: "any character" },
|
50 | peg$c7 = function(c) {
|
51 | return c;
|
52 | },
|
53 | peg$c8 = function(i, c, d) {
|
54 | var out = '';
|
55 | if(i){
|
56 | out = out + TERM_CHAR + i;
|
57 | }
|
58 | out = out + c.join(TERM_CHAR);
|
59 | if(d){
|
60 | if(lastChar(out) !== DEDENT_CHAR){
|
61 | out = out + TERM_CHAR;
|
62 | }
|
63 | out = out + d;
|
64 | }
|
65 | return out;
|
66 | },
|
67 | peg$c9 = function(line, e, children) {
|
68 | var out = line.join('');
|
69 | if(children){
|
70 | out = out + children;
|
71 | }
|
72 | return out;
|
73 | },
|
74 | peg$c10 = "\r\n",
|
75 | peg$c11 = { type: "literal", value: "\r\n", description: "\"\\r\\n\"" },
|
76 | peg$c12 = "\n",
|
77 | peg$c13 = { type: "literal", value: "\n", description: "\"\\n\"" },
|
78 | peg$c14 = "\r",
|
79 | peg$c15 = { type: "literal", value: "\r", description: "\"\\r\"" },
|
80 | peg$c16 = /^[ \t]/,
|
81 | peg$c17 = { type: "class", value: "[ \\t]", description: "[ \\t]" },
|
82 | peg$c18 = function(i) { return i.join("") === indent; },
|
83 | peg$c19 = { type: "other", description: "INDENT" },
|
84 | peg$c20 = function(i) { return i.length > indent.length; },
|
85 | peg$c21 = function(i) {
|
86 | indentStack.push(indent);
|
87 | indent = i.join('');
|
88 | pos = offset;
|
89 | },
|
90 | peg$c22 = function() {
|
91 | return INDENT_CHAR;
|
92 | },
|
93 | peg$c23 = { type: "other", description: "DEDENT" },
|
94 | peg$c24 = function() {
|
95 | indent = indentStack.pop();
|
96 | return DEDENT_CHAR;
|
97 | },
|
98 |
|
99 | peg$currPos = 0,
|
100 | peg$reportedPos = 0,
|
101 | peg$cachedPos = 0,
|
102 | peg$cachedPosDetails = { line: 1, column: 1, seenCR: false },
|
103 | peg$maxFailPos = 0,
|
104 | peg$maxFailExpected = [],
|
105 | peg$silentFails = 0,
|
106 |
|
107 | peg$result;
|
108 |
|
109 | if ("startRule" in options) {
|
110 | if (!(options.startRule in peg$startRuleFunctions)) {
|
111 | throw new Error("Can't start parsing from rule \"" + options.startRule + "\".");
|
112 | }
|
113 |
|
114 | peg$startRuleFunction = peg$startRuleFunctions[options.startRule];
|
115 | }
|
116 |
|
117 | function text() {
|
118 | return input.substring(peg$reportedPos, peg$currPos);
|
119 | }
|
120 |
|
121 | function offset() {
|
122 | return peg$reportedPos;
|
123 | }
|
124 |
|
125 | function line() {
|
126 | return peg$computePosDetails(peg$reportedPos).line;
|
127 | }
|
128 |
|
129 | function column() {
|
130 | return peg$computePosDetails(peg$reportedPos).column;
|
131 | }
|
132 |
|
133 | function expected(description) {
|
134 | throw peg$buildException(
|
135 | null,
|
136 | [{ type: "other", description: description }],
|
137 | peg$reportedPos
|
138 | );
|
139 | }
|
140 |
|
141 | function error(message) {
|
142 | throw peg$buildException(message, null, peg$reportedPos);
|
143 | }
|
144 |
|
145 | function peg$computePosDetails(pos) {
|
146 | function advance(details, startPos, endPos) {
|
147 | var p, ch;
|
148 |
|
149 | for (p = startPos; p < endPos; p++) {
|
150 | ch = input.charAt(p);
|
151 | if (ch === "\n") {
|
152 | if (!details.seenCR) { details.line++; }
|
153 | details.column = 1;
|
154 | details.seenCR = false;
|
155 | } else if (ch === "\r" || ch === "\u2028" || ch === "\u2029") {
|
156 | details.line++;
|
157 | details.column = 1;
|
158 | details.seenCR = true;
|
159 | } else {
|
160 | details.column++;
|
161 | details.seenCR = false;
|
162 | }
|
163 | }
|
164 | }
|
165 |
|
166 | if (peg$cachedPos !== pos) {
|
167 | if (peg$cachedPos > pos) {
|
168 | peg$cachedPos = 0;
|
169 | peg$cachedPosDetails = { line: 1, column: 1, seenCR: false };
|
170 | }
|
171 | advance(peg$cachedPosDetails, peg$cachedPos, pos);
|
172 | peg$cachedPos = pos;
|
173 | }
|
174 |
|
175 | return peg$cachedPosDetails;
|
176 | }
|
177 |
|
178 | function peg$fail(expected) {
|
179 | if (peg$currPos < peg$maxFailPos) { return; }
|
180 |
|
181 | if (peg$currPos > peg$maxFailPos) {
|
182 | peg$maxFailPos = peg$currPos;
|
183 | peg$maxFailExpected = [];
|
184 | }
|
185 |
|
186 | peg$maxFailExpected.push(expected);
|
187 | }
|
188 |
|
189 | function peg$buildException(message, expected, pos) {
|
190 | function cleanupExpected(expected) {
|
191 | var i = 1;
|
192 |
|
193 | expected.sort(function(a, b) {
|
194 | if (a.description < b.description) {
|
195 | return -1;
|
196 | } else if (a.description > b.description) {
|
197 | return 1;
|
198 | } else {
|
199 | return 0;
|
200 | }
|
201 | });
|
202 |
|
203 | while (i < expected.length) {
|
204 | if (expected[i - 1] === expected[i]) {
|
205 | expected.splice(i, 1);
|
206 | } else {
|
207 | i++;
|
208 | }
|
209 | }
|
210 | }
|
211 |
|
212 | function buildMessage(expected, found) {
|
213 | function stringEscape(s) {
|
214 | function hex(ch) { return ch.charCodeAt(0).toString(16).toUpperCase(); }
|
215 |
|
216 | return s
|
217 | .replace(/\\/g, '\\\\')
|
218 | .replace(/"/g, '\\"')
|
219 | .replace(/\x08/g, '\\b')
|
220 | .replace(/\t/g, '\\t')
|
221 | .replace(/\n/g, '\\n')
|
222 | .replace(/\f/g, '\\f')
|
223 | .replace(/\r/g, '\\r')
|
224 | .replace(/[\x00-\x07\x0B\x0E\x0F]/g, function(ch) { return '\\x0' + hex(ch); })
|
225 | .replace(/[\x10-\x1F\x80-\xFF]/g, function(ch) { return '\\x' + hex(ch); })
|
226 | .replace(/[\u0180-\u0FFF]/g, function(ch) { return '\\u0' + hex(ch); })
|
227 | .replace(/[\u1080-\uFFFF]/g, function(ch) { return '\\u' + hex(ch); });
|
228 | }
|
229 |
|
230 | var expectedDescs = new Array(expected.length),
|
231 | expectedDesc, foundDesc, i;
|
232 |
|
233 | for (i = 0; i < expected.length; i++) {
|
234 | expectedDescs[i] = expected[i].description;
|
235 | }
|
236 |
|
237 | expectedDesc = expected.length > 1
|
238 | ? expectedDescs.slice(0, -1).join(", ")
|
239 | + " or "
|
240 | + expectedDescs[expected.length - 1]
|
241 | : expectedDescs[0];
|
242 |
|
243 | foundDesc = found ? "\"" + stringEscape(found) + "\"" : "end of input";
|
244 |
|
245 | return "Expected " + expectedDesc + " but " + foundDesc + " found.";
|
246 | }
|
247 |
|
248 | var posDetails = peg$computePosDetails(pos),
|
249 | found = pos < input.length ? input.charAt(pos) : null;
|
250 |
|
251 | if (expected !== null) {
|
252 | cleanupExpected(expected);
|
253 | }
|
254 |
|
255 | return new SyntaxError(
|
256 | message !== null ? message : buildMessage(expected, found),
|
257 | expected,
|
258 | found,
|
259 | pos,
|
260 | posDetails.line,
|
261 | posDetails.column
|
262 | );
|
263 | }
|
264 |
|
265 | function peg$parsestart() {
|
266 | var s0, s1, s2, s3;
|
267 |
|
268 | s0 = peg$currPos;
|
269 | s1 = peg$parseINDENT();
|
270 | if (s1 === peg$FAILED) {
|
271 | s1 = peg$c1;
|
272 | }
|
273 | if (s1 !== peg$FAILED) {
|
274 | s2 = [];
|
275 | s3 = peg$parseline();
|
276 | while (s3 !== peg$FAILED) {
|
277 | s2.push(s3);
|
278 | s3 = peg$parseline();
|
279 | }
|
280 | if (s2 !== peg$FAILED) {
|
281 | peg$reportedPos = s0;
|
282 | s1 = peg$c3(s2);
|
283 | s0 = s1;
|
284 | } else {
|
285 | peg$currPos = s0;
|
286 | s0 = peg$c0;
|
287 | }
|
288 | } else {
|
289 | peg$currPos = s0;
|
290 | s0 = peg$c0;
|
291 | }
|
292 |
|
293 | return s0;
|
294 | }
|
295 |
|
296 | function peg$parseline() {
|
297 | var s0, s1, s2, s3, s4, s5, s6, s7;
|
298 |
|
299 | s0 = peg$currPos;
|
300 | s1 = peg$parseEOL();
|
301 | if (s1 !== peg$FAILED) {
|
302 | peg$reportedPos = s0;
|
303 | s1 = peg$c4();
|
304 | }
|
305 | s0 = s1;
|
306 | if (s0 === peg$FAILED) {
|
307 | s0 = peg$currPos;
|
308 | s1 = peg$parseSAMEDENT();
|
309 | if (s1 !== peg$FAILED) {
|
310 | s2 = [];
|
311 | s3 = peg$currPos;
|
312 | s4 = peg$currPos;
|
313 | peg$silentFails++;
|
314 | s5 = peg$parseEOL();
|
315 | peg$silentFails--;
|
316 | if (s5 === peg$FAILED) {
|
317 | s4 = peg$c5;
|
318 | } else {
|
319 | peg$currPos = s4;
|
320 | s4 = peg$c0;
|
321 | }
|
322 | if (s4 !== peg$FAILED) {
|
323 | if (input.length > peg$currPos) {
|
324 | s5 = input.charAt(peg$currPos);
|
325 | peg$currPos++;
|
326 | } else {
|
327 | s5 = peg$FAILED;
|
328 | if (peg$silentFails === 0) { peg$fail(peg$c6); }
|
329 | }
|
330 | if (s5 !== peg$FAILED) {
|
331 | peg$reportedPos = s3;
|
332 | s4 = peg$c7(s5);
|
333 | s3 = s4;
|
334 | } else {
|
335 | peg$currPos = s3;
|
336 | s3 = peg$c0;
|
337 | }
|
338 | } else {
|
339 | peg$currPos = s3;
|
340 | s3 = peg$c0;
|
341 | }
|
342 | if (s3 !== peg$FAILED) {
|
343 | while (s3 !== peg$FAILED) {
|
344 | s2.push(s3);
|
345 | s3 = peg$currPos;
|
346 | s4 = peg$currPos;
|
347 | peg$silentFails++;
|
348 | s5 = peg$parseEOL();
|
349 | peg$silentFails--;
|
350 | if (s5 === peg$FAILED) {
|
351 | s4 = peg$c5;
|
352 | } else {
|
353 | peg$currPos = s4;
|
354 | s4 = peg$c0;
|
355 | }
|
356 | if (s4 !== peg$FAILED) {
|
357 | if (input.length > peg$currPos) {
|
358 | s5 = input.charAt(peg$currPos);
|
359 | peg$currPos++;
|
360 | } else {
|
361 | s5 = peg$FAILED;
|
362 | if (peg$silentFails === 0) { peg$fail(peg$c6); }
|
363 | }
|
364 | if (s5 !== peg$FAILED) {
|
365 | peg$reportedPos = s3;
|
366 | s4 = peg$c7(s5);
|
367 | s3 = s4;
|
368 | } else {
|
369 | peg$currPos = s3;
|
370 | s3 = peg$c0;
|
371 | }
|
372 | } else {
|
373 | peg$currPos = s3;
|
374 | s3 = peg$c0;
|
375 | }
|
376 | }
|
377 | } else {
|
378 | s2 = peg$c0;
|
379 | }
|
380 | if (s2 !== peg$FAILED) {
|
381 | s3 = peg$parseEOL();
|
382 | if (s3 === peg$FAILED) {
|
383 | s3 = peg$c1;
|
384 | }
|
385 | if (s3 !== peg$FAILED) {
|
386 | s4 = peg$currPos;
|
387 | s5 = peg$parseINDENT();
|
388 | if (s5 !== peg$FAILED) {
|
389 | s6 = [];
|
390 | s7 = peg$parseline();
|
391 | while (s7 !== peg$FAILED) {
|
392 | s6.push(s7);
|
393 | s7 = peg$parseline();
|
394 | }
|
395 | if (s6 !== peg$FAILED) {
|
396 | s7 = peg$parseDEDENT();
|
397 | if (s7 !== peg$FAILED) {
|
398 | peg$reportedPos = s4;
|
399 | s5 = peg$c8(s5, s6, s7);
|
400 | s4 = s5;
|
401 | } else {
|
402 | peg$currPos = s4;
|
403 | s4 = peg$c0;
|
404 | }
|
405 | } else {
|
406 | peg$currPos = s4;
|
407 | s4 = peg$c0;
|
408 | }
|
409 | } else {
|
410 | peg$currPos = s4;
|
411 | s4 = peg$c0;
|
412 | }
|
413 | if (s4 === peg$FAILED) {
|
414 | s4 = peg$c1;
|
415 | }
|
416 | if (s4 !== peg$FAILED) {
|
417 | peg$reportedPos = s0;
|
418 | s1 = peg$c9(s2, s3, s4);
|
419 | s0 = s1;
|
420 | } else {
|
421 | peg$currPos = s0;
|
422 | s0 = peg$c0;
|
423 | }
|
424 | } else {
|
425 | peg$currPos = s0;
|
426 | s0 = peg$c0;
|
427 | }
|
428 | } else {
|
429 | peg$currPos = s0;
|
430 | s0 = peg$c0;
|
431 | }
|
432 | } else {
|
433 | peg$currPos = s0;
|
434 | s0 = peg$c0;
|
435 | }
|
436 | }
|
437 |
|
438 | return s0;
|
439 | }
|
440 |
|
441 | function peg$parseEOL() {
|
442 | var s0;
|
443 |
|
444 | if (input.substr(peg$currPos, 2) === peg$c10) {
|
445 | s0 = peg$c10;
|
446 | peg$currPos += 2;
|
447 | } else {
|
448 | s0 = peg$FAILED;
|
449 | if (peg$silentFails === 0) { peg$fail(peg$c11); }
|
450 | }
|
451 | if (s0 === peg$FAILED) {
|
452 | if (input.charCodeAt(peg$currPos) === 10) {
|
453 | s0 = peg$c12;
|
454 | peg$currPos++;
|
455 | } else {
|
456 | s0 = peg$FAILED;
|
457 | if (peg$silentFails === 0) { peg$fail(peg$c13); }
|
458 | }
|
459 | if (s0 === peg$FAILED) {
|
460 | if (input.charCodeAt(peg$currPos) === 13) {
|
461 | s0 = peg$c14;
|
462 | peg$currPos++;
|
463 | } else {
|
464 | s0 = peg$FAILED;
|
465 | if (peg$silentFails === 0) { peg$fail(peg$c15); }
|
466 | }
|
467 | }
|
468 | }
|
469 |
|
470 | return s0;
|
471 | }
|
472 |
|
473 | function peg$parseSAMEDENT() {
|
474 | var s0, s1, s2;
|
475 |
|
476 | s0 = peg$currPos;
|
477 | s1 = [];
|
478 | if (peg$c16.test(input.charAt(peg$currPos))) {
|
479 | s2 = input.charAt(peg$currPos);
|
480 | peg$currPos++;
|
481 | } else {
|
482 | s2 = peg$FAILED;
|
483 | if (peg$silentFails === 0) { peg$fail(peg$c17); }
|
484 | }
|
485 | while (s2 !== peg$FAILED) {
|
486 | s1.push(s2);
|
487 | if (peg$c16.test(input.charAt(peg$currPos))) {
|
488 | s2 = input.charAt(peg$currPos);
|
489 | peg$currPos++;
|
490 | } else {
|
491 | s2 = peg$FAILED;
|
492 | if (peg$silentFails === 0) { peg$fail(peg$c17); }
|
493 | }
|
494 | }
|
495 | if (s1 !== peg$FAILED) {
|
496 | peg$reportedPos = peg$currPos;
|
497 | s2 = peg$c18(s1);
|
498 | if (s2) {
|
499 | s2 = peg$c5;
|
500 | } else {
|
501 | s2 = peg$c0;
|
502 | }
|
503 | if (s2 !== peg$FAILED) {
|
504 | s1 = [s1, s2];
|
505 | s0 = s1;
|
506 | } else {
|
507 | peg$currPos = s0;
|
508 | s0 = peg$c0;
|
509 | }
|
510 | } else {
|
511 | peg$currPos = s0;
|
512 | s0 = peg$c0;
|
513 | }
|
514 |
|
515 | return s0;
|
516 | }
|
517 |
|
518 | function peg$parseINDENT() {
|
519 | var s0, s1, s2, s3, s4;
|
520 |
|
521 | peg$silentFails++;
|
522 | s0 = peg$currPos;
|
523 | s1 = peg$currPos;
|
524 | peg$silentFails++;
|
525 | s2 = peg$currPos;
|
526 | s3 = [];
|
527 | if (peg$c16.test(input.charAt(peg$currPos))) {
|
528 | s4 = input.charAt(peg$currPos);
|
529 | peg$currPos++;
|
530 | } else {
|
531 | s4 = peg$FAILED;
|
532 | if (peg$silentFails === 0) { peg$fail(peg$c17); }
|
533 | }
|
534 | if (s4 !== peg$FAILED) {
|
535 | while (s4 !== peg$FAILED) {
|
536 | s3.push(s4);
|
537 | if (peg$c16.test(input.charAt(peg$currPos))) {
|
538 | s4 = input.charAt(peg$currPos);
|
539 | peg$currPos++;
|
540 | } else {
|
541 | s4 = peg$FAILED;
|
542 | if (peg$silentFails === 0) { peg$fail(peg$c17); }
|
543 | }
|
544 | }
|
545 | } else {
|
546 | s3 = peg$c0;
|
547 | }
|
548 | if (s3 !== peg$FAILED) {
|
549 | peg$reportedPos = peg$currPos;
|
550 | s4 = peg$c20(s3);
|
551 | if (s4) {
|
552 | s4 = peg$c5;
|
553 | } else {
|
554 | s4 = peg$c0;
|
555 | }
|
556 | if (s4 !== peg$FAILED) {
|
557 | peg$reportedPos = s2;
|
558 | s3 = peg$c21(s3);
|
559 | s2 = s3;
|
560 | } else {
|
561 | peg$currPos = s2;
|
562 | s2 = peg$c0;
|
563 | }
|
564 | } else {
|
565 | peg$currPos = s2;
|
566 | s2 = peg$c0;
|
567 | }
|
568 | peg$silentFails--;
|
569 | if (s2 !== peg$FAILED) {
|
570 | peg$currPos = s1;
|
571 | s1 = peg$c5;
|
572 | } else {
|
573 | s1 = peg$c0;
|
574 | }
|
575 | if (s1 !== peg$FAILED) {
|
576 | peg$reportedPos = s0;
|
577 | s1 = peg$c22();
|
578 | }
|
579 | s0 = s1;
|
580 | peg$silentFails--;
|
581 | if (s0 === peg$FAILED) {
|
582 | s1 = peg$FAILED;
|
583 | if (peg$silentFails === 0) { peg$fail(peg$c19); }
|
584 | }
|
585 |
|
586 | return s0;
|
587 | }
|
588 |
|
589 | function peg$parseDEDENT() {
|
590 | var s0, s1;
|
591 |
|
592 | peg$silentFails++;
|
593 | s0 = peg$currPos;
|
594 | s1 = [];
|
595 | if (s1 !== peg$FAILED) {
|
596 | peg$reportedPos = s0;
|
597 | s1 = peg$c24();
|
598 | }
|
599 | s0 = s1;
|
600 | peg$silentFails--;
|
601 | if (s0 === peg$FAILED) {
|
602 | s1 = peg$FAILED;
|
603 | if (peg$silentFails === 0) { peg$fail(peg$c23); }
|
604 | }
|
605 |
|
606 | return s0;
|
607 | }
|
608 |
|
609 |
|
610 | var indentStack = [],
|
611 | indent = "",
|
612 | INDENT_CHAR = options.INDENT_CHAR || '\uEFEF',
|
613 | DEDENT_CHAR = options.DEDENT_CHAR || '\uEFFE',
|
614 | TERM_CHAR = options.TERM_CHAR || '\uEFFF';
|
615 |
|
616 | function isArray(obj) {
|
617 | return Object.prototype.toString.call(obj) === '[object Array]';
|
618 | }
|
619 |
|
620 | function compact(arr) {
|
621 | if (!isArray(arr)) {
|
622 | return arr;
|
623 | } else {
|
624 | return arr.filter( function(elem) {
|
625 | return typeof(elem) !== 'undefined'
|
626 | } ).map(compact)
|
627 | }
|
628 | }
|
629 |
|
630 | function lastChar(str){
|
631 | return str.slice(-1);
|
632 | }
|
633 |
|
634 |
|
635 |
|
636 | peg$result = peg$startRuleFunction();
|
637 |
|
638 | if (peg$result !== peg$FAILED && peg$currPos === input.length) {
|
639 | return peg$result;
|
640 | } else {
|
641 | if (peg$result !== peg$FAILED && peg$currPos < input.length) {
|
642 | peg$fail({ type: "end", description: "end of input" });
|
643 | }
|
644 |
|
645 | throw peg$buildException(null, peg$maxFailExpected, peg$maxFailPos);
|
646 | }
|
647 | }
|
648 |
|
649 | return {
|
650 | SyntaxError: SyntaxError,
|
651 | parse: parse
|
652 | };
|
653 | })(); |
\ | No newline at end of file |