OLD | NEW |
(Empty) | |
| 1 // Generated by PEG.js 0.8.0. http://pegjs.majda.cz/ |
| 2 // |
| 3 // ====================================================== |
| 4 // This file contains a parser for the following grammar: |
| 5 // ====================================================== |
| 6 // |
| 7 // start = " "* name:$[a-zA-Z.]+ " "* children:ExprList { |
| 8 // return {site:name, frames:children}; |
| 9 // } |
| 10 // |
| 11 // ExprList = "(" l:CommaSeparatedChildExprs ")" { return l; } |
| 12 // / "(" " "* ")" { return [];} |
| 13 // / {return [];} |
| 14 // |
| 15 // CommaSeparatedChildExprs = start:(e:ChildExpr " "* "," " "* {return e;})* |
| 16 // last:ChildExpr " "* { |
| 17 // return start.concat(last); |
| 18 // } |
| 19 // |
| 20 // ChildExpr = " "* name:$[a-zA-Z.]+ " "* children:$ExprList { |
| 21 // return {site:name, args: name + " " + children}; |
| 22 // } |
| 23 // |
| 24 // ============================================================================ |
| 25 // Example input / output: |
| 26 // ============================================================================ |
| 27 // input = |
| 28 // "a.com (y.com ( ) , x.org, z.net (c.org, z.com (a.com, d.net())))"; |
| 29 // |
| 30 // output = { |
| 31 // "site": "a.com", |
| 32 // "frames": [ |
| 33 // { |
| 34 // "site": "b.com", |
| 35 // "args": "b.com ( )" |
| 36 // }, |
| 37 // { |
| 38 // "site": "c.dotcom", |
| 39 // "args": "c.dotcom " |
| 40 // }, |
| 41 // { |
| 42 // "site": "d.com", |
| 43 // "args": "d.com ( fcom , dcom ( com, com( ) ) )" |
| 44 // } |
| 45 // ] |
| 46 // }; |
| 47 |
| 48 query_parser = (function() { |
| 49 function peg$subclass(child, parent) { |
| 50 function ctor() { this.constructor = child; } |
| 51 ctor.prototype = parent.prototype; |
| 52 child.prototype = new ctor(); |
| 53 } |
| 54 |
| 55 function SyntaxError(message, expected, found, offset, line, column) { |
| 56 this.message = message; |
| 57 this.expected = expected; |
| 58 this.found = found; |
| 59 this.offset = offset; |
| 60 this.line = line; |
| 61 this.column = column; |
| 62 |
| 63 this.name = "SyntaxError"; |
| 64 } |
| 65 |
| 66 peg$subclass(SyntaxError, Error); |
| 67 |
| 68 function parse(input) { |
| 69 var options = arguments.length > 1 ? arguments[1] : {}, |
| 70 |
| 71 peg$FAILED = {}, |
| 72 |
| 73 peg$startRuleIndices = { start: 0 }, |
| 74 peg$startRuleIndex = 0, |
| 75 |
| 76 peg$consts = [ |
| 77 peg$FAILED, |
| 78 [], |
| 79 " ", |
| 80 { type: "literal", value: " ", description: "\" \"" }, |
| 81 /^[a-zA-Z.]/, |
| 82 { type: "class", value: "[a-zA-Z.]", description: "[a-zA-Z.]" }, |
| 83 function(name, children) { |
| 84 return {site:name, frames:children}; |
| 85 }, |
| 86 "(", |
| 87 { type: "literal", value: "(", description: "\"(\"" }, |
| 88 ")", |
| 89 { type: "literal", value: ")", description: "\")\"" }, |
| 90 function(l) { return l; }, |
| 91 function() { return [];}, |
| 92 function() {return [];}, |
| 93 ",", |
| 94 { type: "literal", value: ",", description: "\",\"" }, |
| 95 function(e) {return e;}, |
| 96 function(start, last) { |
| 97 return start.concat(last); |
| 98 }, |
| 99 function(name, children) { |
| 100 return {site:name, args: name + " " + children}; |
| 101 } |
| 102 ], |
| 103 |
| 104 peg$bytecode = [ |
| 105 peg$decode("! !.\"\"\"2\"3#,)&.\"\"\"2\"3#\"+|$! !0$\"\"1!3%+,$,)&0$\"
\"1!3%\"\"\" +! (%+Q% !.\"\"\"2\"3#,)&.\"\"\"2\"3#\"+3%7!+)%4$6&$\"\" %$$# $##
$\"# \"# "), |
| 106 peg$decode("!.'\"\"2'3(+B$7\"+8%.)\"\"2)3*+(%4#6+#!!%$## $\"# \"# *
w \"!.'\"\"2'3(+U$ !.\"\"\"2\"3#,)&.\"\"\"2\"3#\"+7%.)\"\"2)3*+'%4#6,# %$## $\"
# \"# *. \"! !+& 4!6-! %"), |
| 107 peg$decode("! !!7#+t$ !.\"\"\"2\"3#,)&.\"\"\"2\"3#\"+V%..\"\"2.3/+F% !
.\"\"\"2\"3#,)&.\"\"\"2\"3#\"+(%4$60$!#%$$# $## $\"# \"# ,&!7#+t$ !.\"\"\"2
\"3#,)&.\"\"\"2\"3#\"+V%..\"\"2.3/+F% !.\"\"\"2\"3#,)&.\"\"\"2\"3#\"+(%4$60$!#%$
$# $## $\"# \"# \"+Q$7#+G% !.\"\"\"2\"3#,)&.\"\"\"2\"3#\"+)%4#61#\"\"!%$##
$\"# \"# "), |
| 108 peg$decode("! !.\"\"\"2\"3#,)&.\"\"\"2\"3#\"+\x82$! !0$\"\"1!3%+,$,)&0
$\"\"1!3%\"\"\" +! (%+W% !.\"\"\"2\"3#,)&.\"\"\"2\"3#\"+9%!7!+! (%+)%4$62$\"\"
%$$# $## $\"# \"# ") |
| 109 ], |
| 110 |
| 111 peg$currPos = 0, |
| 112 peg$reportedPos = 0, |
| 113 peg$cachedPos = 0, |
| 114 peg$cachedPosDetails = { line: 1, column: 1, seenCR: false }, |
| 115 peg$maxFailPos = 0, |
| 116 peg$maxFailExpected = [], |
| 117 peg$silentFails = 0, |
| 118 |
| 119 peg$result; |
| 120 |
| 121 if ("startRule" in options) { |
| 122 if (!(options.startRule in peg$startRuleIndices)) { |
| 123 throw new Error("Can't start parsing from rule \"" + options.startRule +
"\"."); |
| 124 } |
| 125 |
| 126 peg$startRuleIndex = peg$startRuleIndices[options.startRule]; |
| 127 } |
| 128 |
| 129 function text() { |
| 130 return input.substring(peg$reportedPos, peg$currPos); |
| 131 } |
| 132 |
| 133 function offset() { |
| 134 return peg$reportedPos; |
| 135 } |
| 136 |
| 137 function line() { |
| 138 return peg$computePosDetails(peg$reportedPos).line; |
| 139 } |
| 140 |
| 141 function column() { |
| 142 return peg$computePosDetails(peg$reportedPos).column; |
| 143 } |
| 144 |
| 145 function expected(description) { |
| 146 throw peg$buildException( |
| 147 null, |
| 148 [{ type: "other", description: description }], |
| 149 peg$reportedPos |
| 150 ); |
| 151 } |
| 152 |
| 153 function error(message) { |
| 154 throw peg$buildException(message, null, peg$reportedPos); |
| 155 } |
| 156 |
| 157 function peg$computePosDetails(pos) { |
| 158 function advance(details, startPos, endPos) { |
| 159 var p, ch; |
| 160 |
| 161 for (p = startPos; p < endPos; p++) { |
| 162 ch = input.charAt(p); |
| 163 if (ch === "\n") { |
| 164 if (!details.seenCR) { details.line++; } |
| 165 details.column = 1; |
| 166 details.seenCR = false; |
| 167 } else if (ch === "\r" || ch === "\u2028" || ch === "\u2029") { |
| 168 details.line++; |
| 169 details.column = 1; |
| 170 details.seenCR = true; |
| 171 } else { |
| 172 details.column++; |
| 173 details.seenCR = false; |
| 174 } |
| 175 } |
| 176 } |
| 177 |
| 178 if (peg$cachedPos !== pos) { |
| 179 if (peg$cachedPos > pos) { |
| 180 peg$cachedPos = 0; |
| 181 peg$cachedPosDetails = { line: 1, column: 1, seenCR: false }; |
| 182 } |
| 183 advance(peg$cachedPosDetails, peg$cachedPos, pos); |
| 184 peg$cachedPos = pos; |
| 185 } |
| 186 |
| 187 return peg$cachedPosDetails; |
| 188 } |
| 189 |
| 190 function peg$fail(expected) { |
| 191 if (peg$currPos < peg$maxFailPos) { return; } |
| 192 |
| 193 if (peg$currPos > peg$maxFailPos) { |
| 194 peg$maxFailPos = peg$currPos; |
| 195 peg$maxFailExpected = []; |
| 196 } |
| 197 |
| 198 peg$maxFailExpected.push(expected); |
| 199 } |
| 200 |
| 201 function peg$buildException(message, expected, pos) { |
| 202 function cleanupExpected(expected) { |
| 203 var i = 1; |
| 204 |
| 205 expected.sort(function(a, b) { |
| 206 if (a.description < b.description) { |
| 207 return -1; |
| 208 } else if (a.description > b.description) { |
| 209 return 1; |
| 210 } else { |
| 211 return 0; |
| 212 } |
| 213 }); |
| 214 |
| 215 while (i < expected.length) { |
| 216 if (expected[i - 1] === expected[i]) { |
| 217 expected.splice(i, 1); |
| 218 } else { |
| 219 i++; |
| 220 } |
| 221 } |
| 222 } |
| 223 |
| 224 function buildMessage(expected, found) { |
| 225 function stringEscape(s) { |
| 226 function hex(ch) { return ch.charCodeAt(0).toString(16).toUpperCase();
} |
| 227 |
| 228 return s |
| 229 .replace(/\\/g, '\\\\') |
| 230 .replace(/"/g, '\\"') |
| 231 .replace(/\x08/g, '\\b') |
| 232 .replace(/\t/g, '\\t') |
| 233 .replace(/\n/g, '\\n') |
| 234 .replace(/\f/g, '\\f') |
| 235 .replace(/\r/g, '\\r') |
| 236 .replace(/[\x00-\x07\x0B\x0E\x0F]/g, function(ch) { return '\\x0' +
hex(ch); }) |
| 237 .replace(/[\x10-\x1F\x80-\xFF]/g, function(ch) { return '\\x' +
hex(ch); }) |
| 238 .replace(/[\u0180-\u0FFF]/g, function(ch) { return '\\u0' +
hex(ch); }) |
| 239 .replace(/[\u1080-\uFFFF]/g, function(ch) { return '\\u' +
hex(ch); }); |
| 240 } |
| 241 |
| 242 var expectedDescs = new Array(expected.length), |
| 243 expectedDesc, foundDesc, i; |
| 244 |
| 245 for (i = 0; i < expected.length; i++) { |
| 246 expectedDescs[i] = expected[i].description; |
| 247 } |
| 248 |
| 249 expectedDesc = expected.length > 1 |
| 250 ? expectedDescs.slice(0, -1).join(", ") |
| 251 + " or " |
| 252 + expectedDescs[expected.length - 1] |
| 253 : expectedDescs[0]; |
| 254 |
| 255 foundDesc = found ? "\"" + stringEscape(found) + "\"" : "end of input"; |
| 256 |
| 257 return "Expected " + expectedDesc + " but " + foundDesc + " found."; |
| 258 } |
| 259 |
| 260 var posDetails = peg$computePosDetails(pos), |
| 261 found = pos < input.length ? input.charAt(pos) : null; |
| 262 |
| 263 if (expected !== null) { |
| 264 cleanupExpected(expected); |
| 265 } |
| 266 |
| 267 return new SyntaxError( |
| 268 message !== null ? message : buildMessage(expected, found), |
| 269 expected, |
| 270 found, |
| 271 pos, |
| 272 posDetails.line, |
| 273 posDetails.column |
| 274 ); |
| 275 } |
| 276 |
| 277 function peg$decode(s) { |
| 278 var bc = new Array(s.length), i; |
| 279 |
| 280 for (i = 0; i < s.length; i++) { |
| 281 bc[i] = s.charCodeAt(i) - 32; |
| 282 } |
| 283 |
| 284 return bc; |
| 285 } |
| 286 |
| 287 function peg$parseRule(index) { |
| 288 var bc = peg$bytecode[index], |
| 289 ip = 0, |
| 290 ips = [], |
| 291 end = bc.length, |
| 292 ends = [], |
| 293 stack = [], |
| 294 params, i; |
| 295 |
| 296 function protect(object) { |
| 297 return Object.prototype.toString.apply(object) === "[object Array]" ? []
: object; |
| 298 } |
| 299 |
| 300 while (true) { |
| 301 while (ip < end) { |
| 302 switch (bc[ip]) { |
| 303 case 0: |
| 304 stack.push(protect(peg$consts[bc[ip + 1]])); |
| 305 ip += 2; |
| 306 break; |
| 307 |
| 308 case 1: |
| 309 stack.push(peg$currPos); |
| 310 ip++; |
| 311 break; |
| 312 |
| 313 case 2: |
| 314 stack.pop(); |
| 315 ip++; |
| 316 break; |
| 317 |
| 318 case 3: |
| 319 peg$currPos = stack.pop(); |
| 320 ip++; |
| 321 break; |
| 322 |
| 323 case 4: |
| 324 stack.length -= bc[ip + 1]; |
| 325 ip += 2; |
| 326 break; |
| 327 |
| 328 case 5: |
| 329 stack.splice(-2, 1); |
| 330 ip++; |
| 331 break; |
| 332 |
| 333 case 6: |
| 334 stack[stack.length - 2].push(stack.pop()); |
| 335 ip++; |
| 336 break; |
| 337 |
| 338 case 7: |
| 339 stack.push(stack.splice(stack.length - bc[ip + 1], bc[ip + 1])); |
| 340 ip += 2; |
| 341 break; |
| 342 |
| 343 case 8: |
| 344 stack.pop(); |
| 345 stack.push(input.substring(stack[stack.length - 1], peg$currPos)); |
| 346 ip++; |
| 347 break; |
| 348 |
| 349 case 9: |
| 350 ends.push(end); |
| 351 ips.push(ip + 3 + bc[ip + 1] + bc[ip + 2]); |
| 352 |
| 353 if (stack[stack.length - 1]) { |
| 354 end = ip + 3 + bc[ip + 1]; |
| 355 ip += 3; |
| 356 } else { |
| 357 end = ip + 3 + bc[ip + 1] + bc[ip + 2]; |
| 358 ip += 3 + bc[ip + 1]; |
| 359 } |
| 360 |
| 361 break; |
| 362 |
| 363 case 10: |
| 364 ends.push(end); |
| 365 ips.push(ip + 3 + bc[ip + 1] + bc[ip + 2]); |
| 366 |
| 367 if (stack[stack.length - 1] === peg$FAILED) { |
| 368 end = ip + 3 + bc[ip + 1]; |
| 369 ip += 3; |
| 370 } else { |
| 371 end = ip + 3 + bc[ip + 1] + bc[ip + 2]; |
| 372 ip += 3 + bc[ip + 1]; |
| 373 } |
| 374 |
| 375 break; |
| 376 |
| 377 case 11: |
| 378 ends.push(end); |
| 379 ips.push(ip + 3 + bc[ip + 1] + bc[ip + 2]); |
| 380 |
| 381 if (stack[stack.length - 1] !== peg$FAILED) { |
| 382 end = ip + 3 + bc[ip + 1]; |
| 383 ip += 3; |
| 384 } else { |
| 385 end = ip + 3 + bc[ip + 1] + bc[ip + 2]; |
| 386 ip += 3 + bc[ip + 1]; |
| 387 } |
| 388 |
| 389 break; |
| 390 |
| 391 case 12: |
| 392 if (stack[stack.length - 1] !== peg$FAILED) { |
| 393 ends.push(end); |
| 394 ips.push(ip); |
| 395 |
| 396 end = ip + 2 + bc[ip + 1]; |
| 397 ip += 2; |
| 398 } else { |
| 399 ip += 2 + bc[ip + 1]; |
| 400 } |
| 401 |
| 402 break; |
| 403 |
| 404 case 13: |
| 405 ends.push(end); |
| 406 ips.push(ip + 3 + bc[ip + 1] + bc[ip + 2]); |
| 407 |
| 408 if (input.length > peg$currPos) { |
| 409 end = ip + 3 + bc[ip + 1]; |
| 410 ip += 3; |
| 411 } else { |
| 412 end = ip + 3 + bc[ip + 1] + bc[ip + 2]; |
| 413 ip += 3 + bc[ip + 1]; |
| 414 } |
| 415 |
| 416 break; |
| 417 |
| 418 case 14: |
| 419 ends.push(end); |
| 420 ips.push(ip + 4 + bc[ip + 2] + bc[ip + 3]); |
| 421 |
| 422 if (input.substr(peg$currPos, peg$consts[bc[ip + 1]].length) === p
eg$consts[bc[ip + 1]]) { |
| 423 end = ip + 4 + bc[ip + 2]; |
| 424 ip += 4; |
| 425 } else { |
| 426 end = ip + 4 + bc[ip + 2] + bc[ip + 3]; |
| 427 ip += 4 + bc[ip + 2]; |
| 428 } |
| 429 |
| 430 break; |
| 431 |
| 432 case 15: |
| 433 ends.push(end); |
| 434 ips.push(ip + 4 + bc[ip + 2] + bc[ip + 3]); |
| 435 |
| 436 if (input.substr(peg$currPos, peg$consts[bc[ip + 1]].length).toLow
erCase() === peg$consts[bc[ip + 1]]) { |
| 437 end = ip + 4 + bc[ip + 2]; |
| 438 ip += 4; |
| 439 } else { |
| 440 end = ip + 4 + bc[ip + 2] + bc[ip + 3]; |
| 441 ip += 4 + bc[ip + 2]; |
| 442 } |
| 443 |
| 444 break; |
| 445 |
| 446 case 16: |
| 447 ends.push(end); |
| 448 ips.push(ip + 4 + bc[ip + 2] + bc[ip + 3]); |
| 449 |
| 450 if (peg$consts[bc[ip + 1]].test(input.charAt(peg$currPos))) { |
| 451 end = ip + 4 + bc[ip + 2]; |
| 452 ip += 4; |
| 453 } else { |
| 454 end = ip + 4 + bc[ip + 2] + bc[ip + 3]; |
| 455 ip += 4 + bc[ip + 2]; |
| 456 } |
| 457 |
| 458 break; |
| 459 |
| 460 case 17: |
| 461 stack.push(input.substr(peg$currPos, bc[ip + 1])); |
| 462 peg$currPos += bc[ip + 1]; |
| 463 ip += 2; |
| 464 break; |
| 465 |
| 466 case 18: |
| 467 stack.push(peg$consts[bc[ip + 1]]); |
| 468 peg$currPos += peg$consts[bc[ip + 1]].length; |
| 469 ip += 2; |
| 470 break; |
| 471 |
| 472 case 19: |
| 473 stack.push(peg$FAILED); |
| 474 if (peg$silentFails === 0) { |
| 475 peg$fail(peg$consts[bc[ip + 1]]); |
| 476 } |
| 477 ip += 2; |
| 478 break; |
| 479 |
| 480 case 20: |
| 481 peg$reportedPos = stack[stack.length - 1 - bc[ip + 1]]; |
| 482 ip += 2; |
| 483 break; |
| 484 |
| 485 case 21: |
| 486 peg$reportedPos = peg$currPos; |
| 487 ip++; |
| 488 break; |
| 489 |
| 490 case 22: |
| 491 params = bc.slice(ip + 4, ip + 4 + bc[ip + 3]); |
| 492 for (i = 0; i < bc[ip + 3]; i++) { |
| 493 params[i] = stack[stack.length - 1 - params[i]]; |
| 494 } |
| 495 |
| 496 stack.splice( |
| 497 stack.length - bc[ip + 2], |
| 498 bc[ip + 2], |
| 499 peg$consts[bc[ip + 1]].apply(null, params) |
| 500 ); |
| 501 |
| 502 ip += 4 + bc[ip + 3]; |
| 503 break; |
| 504 |
| 505 case 23: |
| 506 stack.push(peg$parseRule(bc[ip + 1])); |
| 507 ip += 2; |
| 508 break; |
| 509 |
| 510 case 24: |
| 511 peg$silentFails++; |
| 512 ip++; |
| 513 break; |
| 514 |
| 515 case 25: |
| 516 peg$silentFails--; |
| 517 ip++; |
| 518 break; |
| 519 |
| 520 default: |
| 521 throw new Error("Invalid opcode: " + bc[ip] + "."); |
| 522 } |
| 523 } |
| 524 |
| 525 if (ends.length > 0) { |
| 526 end = ends.pop(); |
| 527 ip = ips.pop(); |
| 528 } else { |
| 529 break; |
| 530 } |
| 531 } |
| 532 |
| 533 return stack[0]; |
| 534 } |
| 535 |
| 536 peg$result = peg$parseRule(peg$startRuleIndex); |
| 537 |
| 538 if (peg$result !== peg$FAILED && peg$currPos === input.length) { |
| 539 return peg$result; |
| 540 } else { |
| 541 if (peg$result !== peg$FAILED && peg$currPos < input.length) { |
| 542 peg$fail({ type: "end", description: "end of input" }); |
| 543 } |
| 544 |
| 545 throw peg$buildException(null, peg$maxFailExpected, peg$maxFailPos); |
| 546 } |
| 547 } |
| 548 |
| 549 return { |
| 550 SyntaxError: SyntaxError, |
| 551 parse: parse |
| 552 }; |
| 553 })(); |
OLD | NEW |