/* * PEG.js runtime. * * Required by all parsers generated by PEG.js. */ PEG = {}; (function() { /* ===== PEG.ArrayUtils ===== */ /* Array manipulation utility functions. */ PEG.ArrayUtils = { map: function(array, callback) { var result = []; var length = array.length; for (var i = 0; i < length; i++) { result[i] = callback(array[i]); } return result; } }; /* ===== PEG.StringUtils ===== */ /* String manipulation utility functions. */ PEG.StringUtils = { /* * Surrounds the string with quotes and escapes characters inside so that the * result is a valid JavaScript string. */ quote: function(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 + '"'; } }; /* ===== PEG.Parser ===== */ /* Prototype of all parsers generated by PEG.js. */ PEG.Parser = function(startRule) { this._startRule = startRule; } PEG.Parser.prototype = { _matchFailed: function(failure) { if (this._pos > this._rightmostMatchFailuresPos) { this._rightmostMatchFailuresPos = this._pos; this._rightmostMatchFailures = []; } this._rightmostMatchFailures.push(failure); }, /* * 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.Parser.SyntaxError| describing the error. */ parse: function(input) { var that = this; function initialize() { that._input = input; that._pos = 0; that._rightmostMatchFailuresPos = 0; that._rightmostMatchFailures = []; that._cache = {}; } function buildErrorMessage() { function buildExpectedFromMatchFailures(failures) { switch (failures.length) { case 0: return "end of input"; case 1: return failures[0].toString(); default: return PEG.ArrayUtils.map( failures.slice(0, failures.length - 1), function(failure) { return failure.toString(); } ).join(", ") + " or " + failures[failures.length - 1].toString(); } } var expected = buildExpectedFromMatchFailures( that._rightmostMatchFailures ); var pos = Math.max(that._pos, that._rightmostMatchFailuresPos); var actual = pos < that._input.length ? PEG.StringUtils.quote(that._input.charAt(pos)) : "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 input = that._input; var pos = that._rightmostMatchFailuresPos; var line = 1; var column = 1; var seenCR = false; for (var i = 0; i < pos; 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 }; } initialize(); var initialContext = { reportMatchFailures: true }; var result = this["_parse_" + this._startRule](initialContext); /* * The parser is now in one of the following three states: * * 1. The parser successfully parsed the whole input. * * - |result !== null| * - |that._pos === input.length| * - |that._rightmostMatchFailures.length| may or may not contain * something * * 2. The parser successfully parsed only a part of the input. * * - |result !== null| * - |that._pos < input.length| * - |that._rightmostMatchFailures.length| may or may not contain * something * * 3. The parser did not successfully parse any part of the input. * * - |result === null| * - |that._pos === 0| * - |that._rightmostMatchFailures.length| contains at least one failure * * All code following this comment (including called functions) must * handle these states. */ if (result === null || this._pos !== input.length) { var errorPosition = computeErrorPosition(); throw new PEG.Parser.SyntaxError( buildErrorMessage(), errorPosition.line, errorPosition.column ); } return result; }, /* Returns the parser source code. */ toSource: function() { return this._source; } }; /* ===== PEG.Parser.LiteralMatchFailure ===== */ /* Stores information about a literal match failure. */ PEG.Parser.LiteralMatchFailure = function(value) { this._value = value; }; PEG.Parser.LiteralMatchFailure.prototype = { toString: function() { return PEG.StringUtils.quote(this._value); } }; /* ===== PEG.Parser.AnyMatchFailure ===== */ /* Stores information about a failure to match a "." expression. */ PEG.Parser.AnyMatchFailure = function() {} PEG.Parser.AnyMatchFailure.prototype = { toString: function() { return "any character"; } }; /* ===== PEG.Parser.NamedRuleMatchFailure ===== */ /* Stores information about a failure to match a named rule. */ PEG.Parser.NamedRuleMatchFailure = function(displayName) { this._displayName = displayName; } PEG.Parser.NamedRuleMatchFailure.prototype = { toString: function() { return this._displayName; } }; /* ===== PEG.Parser.SyntaxError ===== */ /* Thrown when a parser encounters a syntax error. */ PEG.Parser.SyntaxError = function(message, line, column) { this.name = "PEG.Parser.SyntaxError"; this.message = message; this.line = line; this.column = column; }; PEG.Parser.SyntaxError.prototype = Error.prototype; })();