diff options
author | booo <borgers@mi.fu-berlin.de> | 2011-01-30 01:20:51 +0100 |
---|---|---|
committer | booo <borgers@mi.fu-berlin.de> | 2011-01-30 01:20:51 +0100 |
commit | fb8641c55e99b6a207dcd7507310d9c4b3bbc376 (patch) | |
tree | b3fca2834e63e62a1cb8baef6e884cc9407e6084 /src | |
parent | db5acf7cda7855bb22660f993cc0c25dd27bf631 (diff) | |
download | osm-xapi-fb8641c55e99b6a207dcd7507310d9c4b3bbc376.tar.gz osm-xapi-fb8641c55e99b6a207dcd7507310d9c4b3bbc376.tar.xz osm-xapi-fb8641c55e99b6a207dcd7507310d9c4b3bbc376.zip |
the parsing solution?
Diffstat (limited to 'src')
-rw-r--r-- | src/nodejs/alternative/parser.js | 1168 | ||||
-rw-r--r-- | src/nodejs/alternative/testgrammar | 28 |
2 files changed, 1196 insertions, 0 deletions
diff --git a/src/nodejs/alternative/parser.js b/src/nodejs/alternative/parser.js new file mode 100644 index 0000000..ac10479 --- /dev/null +++ b/src/nodejs/alternative/parser.js @@ -0,0 +1,1168 @@ +exports.parser = parser = (function(){ + /* Generated by PEG.js (http://pegjs.majda.cz/). */ + + var result = { + /* + * Parses the input with a generated parser. If the parsing is successfull, + * returns a value explicitly or implicitly specified by the grammar from + * which the parser was generated (see |PEG.buildParser|). If the parsing is + * unsuccessful, throws |PEG.grammarParser.SyntaxError| describing the error. + */ + parse: function(input) { + var pos = 0; + var rightmostMatchFailuresPos = 0; + var rightmostMatchFailuresExpected = []; + var cache = {}; + + function padLeft(input, padding, length) { + var result = input; + + var padLength = length - input.length; + for (var i = 0; i < padLength; i++) { + result = padding + result; + } + + return result; + } + + function escape(ch) { + var charCode = ch.charCodeAt(0); + + if (charCode <= 0xFF) { + var escapeChar = 'x'; + var length = 2; + } else { + var escapeChar = 'u'; + var length = 4; + } + + return '\\' + escapeChar + padLeft(charCode.toString(16).toUpperCase(), '0', length); + } + + function quoteString(s) { + /* + * ECMA-262, 5th ed., 7.8.4: All characters may appear literally in a + * string literal except for the closing quote character, backslash, + * carriage return, line separator, paragraph separator, and line feed. + * Any character may appear in the form of an escape sequence. + */ + return '"' + s + .replace(/\\/g, '\\\\') // backslash + .replace(/"/g, '\\"') // closing quote character + .replace(/\r/g, '\\r') // carriage return + .replace(/\u2028/g, '\\u2028') // line separator + .replace(/\u2029/g, '\\u2029') // paragraph separator + .replace(/\n/g, '\\n') // line feed + .replace(/[\x80-\uFFFF]/g, escape) // non-ASCII characters + + '"'; + } + + function arrayContains(array, value) { + /* + * Stupid IE does not have Array.prototype.indexOf, otherwise this + * function would be a one-liner. + */ + var length = array.length; + for (var i = 0; i < length; i++) { + if (array[i] === value) { + return true; + } + } + return false; + } + + function matchFailed(failure) { + if (pos < rightmostMatchFailuresPos) { + return; + } + + if (pos > rightmostMatchFailuresPos) { + rightmostMatchFailuresPos = pos; + rightmostMatchFailuresExpected = []; + } + + if (!arrayContains(rightmostMatchFailuresExpected, failure)) { + rightmostMatchFailuresExpected.push(failure); + } + } + + function parse_url(context) { + var cacheKey = "url" + '@' + pos; + var cachedResult = cache[cacheKey]; + if (cachedResult) { + pos = cachedResult.nextPos; + return cachedResult.result; + } + + + var savedPos1 = pos; + var result7 = parse_object(context); + if (result7 !== null) { + var result8 = parse_predicate(context); + if (result8 !== null) { + var result9 = parse_predicate(context); + if (result9 !== null) { + var result6 = [result7, result8, result9]; + } else { + var result6 = null; + pos = savedPos1; + } + } else { + var result6 = null; + pos = savedPos1; + } + } else { + var result6 = null; + pos = savedPos1; + } + var result5 = result6 !== null + ? (function(object, p1, p2) { var result = {object:object}; if(p1.tags != undefined) {result.tags= p1.tags} else if(p1.bbox != undefined) {result.bbox=p1.bbox;} if(p2.tags != undefined) {result.tags= p2.tags} else if(p2.bbox != undefined) {result.bbox=p2.bbox;} return result;})(result6[0], result6[1], result6[2]) + : null; + if (result5 !== null) { + var result0 = result5; + } else { + var savedPos0 = pos; + var result3 = parse_object(context); + if (result3 !== null) { + var result4 = parse_predicate(context); + if (result4 !== null) { + var result2 = [result3, result4]; + } else { + var result2 = null; + pos = savedPos0; + } + } else { + var result2 = null; + pos = savedPos0; + } + if (result2 !== null) { + var result0 = result2; + } else { + var result1 = parse_object(context); + if (result1 !== null) { + var result0 = result1; + } else { + var result0 = null;; + }; + }; + } + + + + cache[cacheKey] = { + nextPos: pos, + result: result0 + }; + return result0; + } + + function parse_object(context) { + var cacheKey = "object" + '@' + pos; + var cachedResult = cache[cacheKey]; + if (cachedResult) { + pos = cachedResult.nextPos; + return cachedResult.result; + } + + + if (input.substr(pos, 4) === "node") { + var result8 = "node"; + pos += 4; + } else { + var result8 = null; + if (context.reportMatchFailures) { + matchFailed(quoteString("node")); + } + } + var result7 = result8 !== null + ? (function(v) {return v})(result8) + : null; + if (result7 !== null) { + var result0 = result7; + } else { + if (input.substr(pos, 3) === "way") { + var result6 = "way"; + pos += 3; + } else { + var result6 = null; + if (context.reportMatchFailures) { + matchFailed(quoteString("way")); + } + } + var result5 = result6 !== null + ? (function(v) {return v})(result6) + : null; + if (result5 !== null) { + var result0 = result5; + } else { + if (input.substr(pos, 8) === "relation") { + var result4 = "relation"; + pos += 8; + } else { + var result4 = null; + if (context.reportMatchFailures) { + matchFailed(quoteString("relation")); + } + } + var result3 = result4 !== null + ? (function(v) {return v})(result4) + : null; + if (result3 !== null) { + var result0 = result3; + } else { + if (input.substr(pos, 1) === "*") { + var result2 = "*"; + pos += 1; + } else { + var result2 = null; + if (context.reportMatchFailures) { + matchFailed(quoteString("*")); + } + } + var result1 = result2 !== null + ? (function(v) {return v})(result2) + : null; + if (result1 !== null) { + var result0 = result1; + } else { + var result0 = null;; + }; + }; + }; + } + + + + cache[cacheKey] = { + nextPos: pos, + result: result0 + }; + return result0; + } + + function parse_predicate(context) { + var cacheKey = "predicate" + '@' + pos; + var cachedResult = cache[cacheKey]; + if (cachedResult) { + pos = cachedResult.nextPos; + return cachedResult.result; + } + + + var result4 = parse_bboxpredicate(context); + if (result4 !== null) { + var result0 = result4; + } else { + var result3 = parse_tagpredicate(context); + var result2 = result3 !== null + ? (function(v) {return {tags:v}})(result3) + : null; + if (result2 !== null) { + var result0 = result2; + } else { + var result1 = parse_childpredicate(context); + if (result1 !== null) { + var result0 = result1; + } else { + var result0 = null;; + }; + }; + } + + + + cache[cacheKey] = { + nextPos: pos, + result: result0 + }; + return result0; + } + + function parse_tagpredicate(context) { + var cacheKey = "tagpredicate" + '@' + pos; + var cachedResult = cache[cacheKey]; + if (cachedResult) { + pos = cachedResult.nextPos; + return cachedResult.result; + } + + + var savedPos0 = pos; + if (input.substr(pos, 1) === "[") { + var result2 = "["; + pos += 1; + } else { + var result2 = null; + if (context.reportMatchFailures) { + matchFailed(quoteString("[")); + } + } + if (result2 !== null) { + var result3 = parse_keys(context); + if (result3 !== null) { + if (input.substr(pos, 1) === "=") { + var result4 = "="; + pos += 1; + } else { + var result4 = null; + if (context.reportMatchFailures) { + matchFailed(quoteString("=")); + } + } + if (result4 !== null) { + var result5 = parse_values(context); + if (result5 !== null) { + if (input.substr(pos, 1) === "]") { + var result6 = "]"; + pos += 1; + } else { + var result6 = null; + if (context.reportMatchFailures) { + matchFailed(quoteString("]")); + } + } + if (result6 !== null) { + var result1 = [result2, result3, result4, result5, result6]; + } else { + var result1 = null; + pos = savedPos0; + } + } else { + var result1 = null; + pos = savedPos0; + } + } else { + var result1 = null; + pos = savedPos0; + } + } else { + var result1 = null; + pos = savedPos0; + } + } else { + var result1 = null; + pos = savedPos0; + } + var result0 = result1 !== null + ? (function(keys, values) {return {keys:keys, values:values}})(result1[1], result1[3]) + : null; + + + + cache[cacheKey] = { + nextPos: pos, + result: result0 + }; + return result0; + } + + function parse_childpredicate(context) { + var cacheKey = "childpredicate" + '@' + pos; + var cachedResult = cache[cacheKey]; + if (cachedResult) { + pos = cachedResult.nextPos; + return cachedResult.result; + } + + + if (input.substr(pos, 7) === "not(nd)") { + var result0 = "not(nd)"; + pos += 7; + } else { + var result0 = null; + if (context.reportMatchFailures) { + matchFailed(quoteString("not(nd)")); + } + } + + + + cache[cacheKey] = { + nextPos: pos, + result: result0 + }; + return result0; + } + + function parse_bboxpredicate(context) { + var cacheKey = "bboxpredicate" + '@' + pos; + var cachedResult = cache[cacheKey]; + if (cachedResult) { + pos = cachedResult.nextPos; + return cachedResult.result; + } + + + var savedPos0 = pos; + if (input.substr(pos, 6) === "[bbox=") { + var result2 = "[bbox="; + pos += 6; + } else { + var result2 = null; + if (context.reportMatchFailures) { + matchFailed(quoteString("[bbox=")); + } + } + if (result2 !== null) { + var result3 = parse_float(context); + if (result3 !== null) { + if (input.substr(pos, 1) === ",") { + var result4 = ","; + pos += 1; + } else { + var result4 = null; + if (context.reportMatchFailures) { + matchFailed(quoteString(",")); + } + } + if (result4 !== null) { + var result5 = parse_float(context); + if (result5 !== null) { + if (input.substr(pos, 1) === ",") { + var result6 = ","; + pos += 1; + } else { + var result6 = null; + if (context.reportMatchFailures) { + matchFailed(quoteString(",")); + } + } + if (result6 !== null) { + var result7 = parse_float(context); + if (result7 !== null) { + if (input.substr(pos, 1) === ",") { + var result8 = ","; + pos += 1; + } else { + var result8 = null; + if (context.reportMatchFailures) { + matchFailed(quoteString(",")); + } + } + if (result8 !== null) { + var result9 = parse_float(context); + if (result9 !== null) { + if (input.substr(pos, 1) === "]") { + var result10 = "]"; + pos += 1; + } else { + var result10 = null; + if (context.reportMatchFailures) { + matchFailed(quoteString("]")); + } + } + if (result10 !== null) { + var result1 = [result2, result3, result4, result5, result6, result7, result8, result9, result10]; + } else { + var result1 = null; + pos = savedPos0; + } + } else { + var result1 = null; + pos = savedPos0; + } + } else { + var result1 = null; + pos = savedPos0; + } + } else { + var result1 = null; + pos = savedPos0; + } + } else { + var result1 = null; + pos = savedPos0; + } + } else { + var result1 = null; + pos = savedPos0; + } + } else { + var result1 = null; + pos = savedPos0; + } + } else { + var result1 = null; + pos = savedPos0; + } + } else { + var result1 = null; + pos = savedPos0; + } + var result0 = result1 !== null + ? (function(left, top, right, bottom) { return {bbox:{left:left,top:top,right:right,bottom:bottom}}})(result1[1], result1[3], result1[5], result1[7]) + : null; + + + + cache[cacheKey] = { + nextPos: pos, + result: result0 + }; + return result0; + } + + function parse_keys(context) { + var cacheKey = "keys" + '@' + pos; + var cachedResult = cache[cacheKey]; + if (cachedResult) { + pos = cachedResult.nextPos; + return cachedResult.result; + } + + + var savedPos0 = pos; + var result5 = parse_key(context); + if (result5 !== null) { + var savedPos1 = pos; + if (input.substr(pos, 1) === "|") { + var result8 = "|"; + pos += 1; + } else { + var result8 = null; + if (context.reportMatchFailures) { + matchFailed(quoteString("|")); + } + } + if (result8 !== null) { + var result9 = parse_keys(context); + if (result9 !== null) { + var result7 = [result8, result9]; + } else { + var result7 = null; + pos = savedPos1; + } + } else { + var result7 = null; + pos = savedPos1; + } + if (result7 !== null) { + var result6 = []; + while (result7 !== null) { + result6.push(result7); + var savedPos1 = pos; + if (input.substr(pos, 1) === "|") { + var result8 = "|"; + pos += 1; + } else { + var result8 = null; + if (context.reportMatchFailures) { + matchFailed(quoteString("|")); + } + } + if (result8 !== null) { + var result9 = parse_keys(context); + if (result9 !== null) { + var result7 = [result8, result9]; + } else { + var result7 = null; + pos = savedPos1; + } + } else { + var result7 = null; + pos = savedPos1; + } + } + } else { + var result6 = null; + } + if (result6 !== null) { + var result4 = [result5, result6]; + } else { + var result4 = null; + pos = savedPos0; + } + } else { + var result4 = null; + pos = savedPos0; + } + var result3 = result4 !== null + ? (function(key, keys) { var result = new Array(); result.push(key); return result.concat(keys[0][1])})(result4[0], result4[1]) + : null; + if (result3 !== null) { + var result0 = result3; + } else { + var result2 = parse_key(context); + var result1 = result2 !== null + ? (function(key) { var result = new Array(); result.push(key); return result})(result2) + : null; + if (result1 !== null) { + var result0 = result1; + } else { + var result0 = null;; + }; + } + + + + cache[cacheKey] = { + nextPos: pos, + result: result0 + }; + return result0; + } + + function parse_values(context) { + var cacheKey = "values" + '@' + pos; + var cachedResult = cache[cacheKey]; + if (cachedResult) { + pos = cachedResult.nextPos; + return cachedResult.result; + } + + + var savedPos0 = pos; + var result5 = parse_value(context); + if (result5 !== null) { + var savedPos1 = pos; + if (input.substr(pos, 1) === "|") { + var result8 = "|"; + pos += 1; + } else { + var result8 = null; + if (context.reportMatchFailures) { + matchFailed(quoteString("|")); + } + } + if (result8 !== null) { + var result9 = parse_values(context); + if (result9 !== null) { + var result7 = [result8, result9]; + } else { + var result7 = null; + pos = savedPos1; + } + } else { + var result7 = null; + pos = savedPos1; + } + if (result7 !== null) { + var result6 = []; + while (result7 !== null) { + result6.push(result7); + var savedPos1 = pos; + if (input.substr(pos, 1) === "|") { + var result8 = "|"; + pos += 1; + } else { + var result8 = null; + if (context.reportMatchFailures) { + matchFailed(quoteString("|")); + } + } + if (result8 !== null) { + var result9 = parse_values(context); + if (result9 !== null) { + var result7 = [result8, result9]; + } else { + var result7 = null; + pos = savedPos1; + } + } else { + var result7 = null; + pos = savedPos1; + } + } + } else { + var result6 = null; + } + if (result6 !== null) { + var result4 = [result5, result6]; + } else { + var result4 = null; + pos = savedPos0; + } + } else { + var result4 = null; + pos = savedPos0; + } + var result3 = result4 !== null + ? (function(value, values) { var result = new Array(); result.push(value); return result.concat(values[0][1])})(result4[0], result4[1]) + : null; + if (result3 !== null) { + var result0 = result3; + } else { + var result2 = parse_value(context); + var result1 = result2 !== null + ? (function(value) { var result = new Array(); result.push(value); return result})(result2) + : null; + if (result1 !== null) { + var result0 = result1; + } else { + var result0 = null;; + }; + } + + + + cache[cacheKey] = { + nextPos: pos, + result: result0 + }; + return result0; + } + + function parse_key(context) { + var cacheKey = "key" + '@' + pos; + var cachedResult = cache[cacheKey]; + if (cachedResult) { + pos = cachedResult.nextPos; + return cachedResult.result; + } + + + var result2 = parse_letter(context); + if (result2 !== null) { + var result1 = []; + while (result2 !== null) { + result1.push(result2); + var result2 = parse_letter(context); + } + } else { + var result1 = null; + } + var result0 = result1 !== null + ? (function(key) {return key.join("")})(result1) + : null; + + + + cache[cacheKey] = { + nextPos: pos, + result: result0 + }; + return result0; + } + + function parse_value(context) { + var cacheKey = "value" + '@' + pos; + var cachedResult = cache[cacheKey]; + if (cachedResult) { + pos = cachedResult.nextPos; + return cachedResult.result; + } + + + var result2 = parse_letter(context); + if (result2 !== null) { + var result1 = []; + while (result2 !== null) { + result1.push(result2); + var result2 = parse_letter(context); + } + } else { + var result1 = null; + } + var result0 = result1 !== null + ? (function(value) {return value.join("")})(result1) + : null; + + + + cache[cacheKey] = { + nextPos: pos, + result: result0 + }; + return result0; + } + + function parse_letter(context) { + var cacheKey = "letter" + '@' + pos; + var cachedResult = cache[cacheKey]; + if (cachedResult) { + pos = cachedResult.nextPos; + return cachedResult.result; + } + + + if (input.substr(pos, 2) === "\\*") { + var result11 = "\\*"; + pos += 2; + } else { + var result11 = null; + if (context.reportMatchFailures) { + matchFailed(quoteString("\\*")); + } + } + var result10 = result11 !== null + ? (function() {return "*"})() + : null; + if (result10 !== null) { + var result0 = result10; + } else { + if (input.substr(pos, 2) === "\\[") { + var result9 = "\\["; + pos += 2; + } else { + var result9 = null; + if (context.reportMatchFailures) { + matchFailed(quoteString("\\[")); + } + } + var result8 = result9 !== null + ? (function() {return "["})() + : null; + if (result8 !== null) { + var result0 = result8; + } else { + if (input.substr(pos, 2) === "\\]") { + var result7 = "\\]"; + pos += 2; + } else { + var result7 = null; + if (context.reportMatchFailures) { + matchFailed(quoteString("\\]")); + } + } + var result6 = result7 !== null + ? (function() {return "]" })() + : null; + if (result6 !== null) { + var result0 = result6; + } else { + if (input.substr(pos, 2) === "\\\\") { + var result5 = "\\\\"; + pos += 2; + } else { + var result5 = null; + if (context.reportMatchFailures) { + matchFailed(quoteString("\\\\")); + } + } + var result4 = result5 !== null + ? (function() {return "\\"})() + : null; + if (result4 !== null) { + var result0 = result4; + } else { + if (input.substr(pos, 2) === "\\|") { + var result3 = "\\|"; + pos += 2; + } else { + var result3 = null; + if (context.reportMatchFailures) { + matchFailed(quoteString("\\|")); + } + } + var result2 = result3 !== null + ? (function() {return "|" })() + : null; + if (result2 !== null) { + var result0 = result2; + } else { + if (input.substr(pos).match(/^[^*|=\\\][]/) !== null) { + var result1 = input.charAt(pos); + pos++; + } else { + var result1 = null; + if (context.reportMatchFailures) { + matchFailed("[^*|=\\\\\\][]"); + } + } + if (result1 !== null) { + var result0 = result1; + } else { + var result0 = null;; + }; + }; + }; + }; + }; + } + + + + cache[cacheKey] = { + nextPos: pos, + result: result0 + }; + return result0; + } + + function parse_float(context) { + var cacheKey = "float" + '@' + pos; + var cachedResult = cache[cacheKey]; + if (cachedResult) { + pos = cachedResult.nextPos; + return cachedResult.result; + } + + + var savedPos1 = pos; + if (input.substr(pos, 1) === "-") { + var result15 = "-"; + pos += 1; + } else { + var result15 = null; + if (context.reportMatchFailures) { + matchFailed(quoteString("-")); + } + } + var result9 = result15 !== null ? result15 : ''; + if (result9 !== null) { + if (input.substr(pos).match(/^[0-9]/) !== null) { + var result14 = input.charAt(pos); + pos++; + } else { + var result14 = null; + if (context.reportMatchFailures) { + matchFailed("[0-9]"); + } + } + if (result14 !== null) { + var result10 = []; + while (result14 !== null) { + result10.push(result14); + if (input.substr(pos).match(/^[0-9]/) !== null) { + var result14 = input.charAt(pos); + pos++; + } else { + var result14 = null; + if (context.reportMatchFailures) { + matchFailed("[0-9]"); + } + } + } + } else { + var result10 = null; + } + if (result10 !== null) { + if (input.substr(pos, 1) === ".") { + var result11 = "."; + pos += 1; + } else { + var result11 = null; + if (context.reportMatchFailures) { + matchFailed(quoteString(".")); + } + } + if (result11 !== null) { + if (input.substr(pos).match(/^[0-9]/) !== null) { + var result13 = input.charAt(pos); + pos++; + } else { + var result13 = null; + if (context.reportMatchFailures) { + matchFailed("[0-9]"); + } + } + if (result13 !== null) { + var result12 = []; + while (result13 !== null) { + result12.push(result13); + if (input.substr(pos).match(/^[0-9]/) !== null) { + var result13 = input.charAt(pos); + pos++; + } else { + var result13 = null; + if (context.reportMatchFailures) { + matchFailed("[0-9]"); + } + } + } + } else { + var result12 = null; + } + if (result12 !== null) { + var result8 = [result9, result10, result11, result12]; + } else { + var result8 = null; + pos = savedPos1; + } + } else { + var result8 = null; + pos = savedPos1; + } + } else { + var result8 = null; + pos = savedPos1; + } + } else { + var result8 = null; + pos = savedPos1; + } + var result7 = result8 !== null + ? (function(m, digits, digits2) { result = parseInt(digits.join(""))+parseFloat("0."+digits2.join("")); if(m == "-") {result=result*-1}; return result})(result8[0], result8[1], result8[3]) + : null; + if (result7 !== null) { + var result0 = result7; + } else { + var savedPos0 = pos; + if (input.substr(pos, 1) === "-") { + var result6 = "-"; + pos += 1; + } else { + var result6 = null; + if (context.reportMatchFailures) { + matchFailed(quoteString("-")); + } + } + var result3 = result6 !== null ? result6 : ''; + if (result3 !== null) { + if (input.substr(pos).match(/^[0-9]/) !== null) { + var result5 = input.charAt(pos); + pos++; + } else { + var result5 = null; + if (context.reportMatchFailures) { + matchFailed("[0-9]"); + } + } + if (result5 !== null) { + var result4 = []; + while (result5 !== null) { + result4.push(result5); + if (input.substr(pos).match(/^[0-9]/) !== null) { + var result5 = input.charAt(pos); + pos++; + } else { + var result5 = null; + if (context.reportMatchFailures) { + matchFailed("[0-9]"); + } + } + } + } else { + var result4 = null; + } + if (result4 !== null) { + var result2 = [result3, result4]; + } else { + var result2 = null; + pos = savedPos0; + } + } else { + var result2 = null; + pos = savedPos0; + } + var result1 = result2 !== null + ? (function(m, digits) { result = parseInt(digits.join("")); if(m == "-") {result = result*-1}; return result})(result2[0], result2[1]) + : null; + if (result1 !== null) { + var result0 = result1; + } else { + var result0 = null;; + }; + } + + + + cache[cacheKey] = { + nextPos: pos, + result: result0 + }; + return result0; + } + + function buildErrorMessage() { + function buildExpected(failuresExpected) { + switch (failuresExpected.length) { + case 0: + return 'end of input'; + case 1: + return failuresExpected[0]; + default: + failuresExpected.sort(); + return failuresExpected.slice(0, failuresExpected.length - 1).join(', ') + + ' or ' + + failuresExpected[failuresExpected.length - 1]; + } + } + + var expected = buildExpected(rightmostMatchFailuresExpected); + var actualPos = Math.max(pos, rightmostMatchFailuresPos); + var actual = actualPos < input.length + ? quoteString(input.charAt(actualPos)) + : 'end of input'; + + return 'Expected ' + expected + ' but ' + actual + ' found.'; + } + + function computeErrorPosition() { + /* + * The first idea was to use |String.split| to break the input up to the + * error position along newlines and derive the line and column from + * there. However IE's |split| implementation is so broken that it was + * enough to prevent it. + */ + + var line = 1; + var column = 1; + var seenCR = false; + + for (var i = 0; i < rightmostMatchFailuresPos; i++) { + var ch = input.charAt(i); + if (ch === '\n') { + if (!seenCR) { line++; } + column = 1; + seenCR = false; + } else if (ch === '\r' | ch === '\u2028' || ch === '\u2029') { + line++; + column = 1; + seenCR = true; + } else { + column++; + seenCR = false; + } + } + + return { line: line, column: column }; + } + + + + var result = parse_url({ reportMatchFailures: true }); + + /* + * The parser is now in one of the following three states: + * + * 1. The parser successfully parsed the whole input. + * + * - |result !== null| + * - |pos === input.length| + * - |rightmostMatchFailuresExpected| may or may not contain something + * + * 2. The parser successfully parsed only a part of the input. + * + * - |result !== null| + * - |pos < input.length| + * - |rightmostMatchFailuresExpected| may or may not contain something + * + * 3. The parser did not successfully parse any part of the input. + * + * - |result === null| + * - |pos === 0| + * - |rightmostMatchFailuresExpected| contains at least one failure + * + * All code following this comment (including called functions) must + * handle these states. + */ + if (result === null || pos !== input.length) { + var errorPosition = computeErrorPosition(); + throw new this.SyntaxError( + buildErrorMessage(), + errorPosition.line, + errorPosition.column + ); + } + + return result; + }, + + /* Returns the parser source code. */ + toSource: function() { return this._source; } + }; + + /* Thrown when a parser encounters a syntax error. */ + + result.SyntaxError = function(message, line, column) { + this.name = 'SyntaxError'; + this.message = message; + this.line = line; + this.column = column; + }; + + result.SyntaxError.prototype = Error.prototype; + + return result; +})(); diff --git a/src/nodejs/alternative/testgrammar b/src/nodejs/alternative/testgrammar new file mode 100644 index 0000000..e212493 --- /dev/null +++ b/src/nodejs/alternative/testgrammar @@ -0,0 +1,28 @@ +/* + * Classic example grammar, which recognizes simple arithmetic expressions like + * "2*(3+4)". The parser generated from this grammar then computes their value. + */ + +url = object:object p1:predicate p2:predicate { var result = {object:object}; if(p1.tags != undefined) {result.tags= p1.tags} else if(p1.bbox != undefined) {result.bbox=p1.bbox;} if(p2.tags != undefined) {result.tags= p2.tags} else if(p2.bbox != undefined) {result.bbox=p2.bbox;} return result;}/ object predicate / object + +object = v:"node" {return v} / v:"way" {return v} / v:"relation" {return v} / v:"*" {return v} + + + +predicate = bboxpredicate / v:tagpredicate {return {tags:v}}/ childpredicate + +tagpredicate = "["keys:keys"="values:values"]" {return {keys:keys, values:values}} + +childpredicate = "not(nd)" +bboxpredicate = "[bbox=" left:float "," top:float","right:float","bottom:float"]" { return {bbox:{left:left,top:top,right:right,bottom:bottom}}} + +keys = key:key keys:("|" keys)+ { var result = new Array(); result.push(key); return result.concat(keys[0][1])} / key:key { var result = new Array(); result.push(key); return result} + +values = value:value values:("|" values)+ { var result = new Array(); result.push(value); return result.concat(values[0][1])} / value:value { var result = new Array(); result.push(value); return result} + +key = key:letter+ {return key.join("")} +value = value:letter+ {return value.join("")} +letter = "\\*" {return "*"} / "\\[" {return "["} / "\\]" {return "]" } / "\\\\" {return "\\"} / "\\|" {return "|" } / [^*|=\\\][] + +//add negative values +float = m:"-"?digits:[0-9]+"."digits2:[0-9]+ { result = parseInt(digits.join(""))+parseFloat("0."+digits2.join("")); if(m == "-") {result=result*-1}; return result} / m:"-"?digits:[0-9]+ { result = parseInt(digits.join("")); if(m == "-") {result = result*-1}; return result} |