@ -465,7 +465,7 @@ PEG.Compiler = {
) ;
var reportMatchFailureCode = PEG . Compiler . formatCode (
"if (context.reportMatchFailures && ${resultVar} === null) {" ,
" this._ matchFailed(${displayName|string});",
" matchFailed(${displayName|string});",
"}" ,
{
displayName : node . displayName ,
@ -479,27 +479,25 @@ PEG.Compiler = {
}
return PEG . Compiler . formatCode (
" _parse_${name}: function (context) {",
" var cacheKey = ${name|string} + '@' + this._ pos;",
" var cachedResult = this._ cache[cacheKey];",
" function parse_${name} (context) {",
" var cacheKey = ${name|string} + '@' + pos;",
" var cachedResult = cache[cacheKey];",
" if (cachedResult) {" ,
" this._ pos = cachedResult.nextPos;",
" pos = cachedResult.nextPos;",
" return cachedResult.result;" ,
" }" ,
" " ,
" var pos = this._pos;" ,
" " ,
" ${setReportMatchFailuresCode}" ,
" ${code}" ,
" ${restoreReportMatchFailuresCode}" ,
" ${reportMatchFailureCode}" ,
" " ,
" this._ cache[cacheKey] = {",
" nextPos: this._ pos,",
" cache[cacheKey] = {",
" nextPos: pos,",
" result: ${resultVar}" ,
" };" ,
" return ${resultVar};" ,
"} , ",
"} ",
{
name : node . name ,
setReportMatchFailuresCode : setReportMatchFailuresCode ,
@ -516,16 +514,15 @@ PEG.Compiler = {
* is as follows :
*
* * The code fragment should try to match a part of the input starting with
* the position indicated in | this . _ pos| . That position may point past the
* end of the input .
* the position indicated in | pos| . That position may point past the end of
* the input .
*
* * If the code fragment matches the input , it advances | this . _ pos| after
* the matched part of the input and sets variable with a name stored in
* * If the code fragment matches the input , it advances | pos| after the
* matched part of the input and sets variable with a name stored in
* | resultVar | to appropriate value , which is always non - null .
*
* * If the code fragment does not match the input , it does not change
* | this . _pos | and it sets a variable with a name stored in | resultVar | to
* | null | .
* * If the code fragment does not match the input , it does not change | pos |
* and it sets a variable with a name stored in | resultVar | to | null | .
* /
choice : function ( node , resultVar ) {
@ -577,7 +574,7 @@ PEG.Compiler = {
" ${code}" ,
"} else {" ,
" var ${resultVar} = null;" ,
" this._ pos = ${savedPosVar};",
" pos = ${savedPosVar};",
"}" ,
{
elementCode : PEG . Compiler . compileNode ( node . elements [ i ] , elementResultVars [ i ] ) ,
@ -590,7 +587,7 @@ PEG.Compiler = {
}
return PEG . Compiler . formatCode (
"var ${savedPosVar} = this._ pos;",
"var ${savedPosVar} = pos;",
"${code}" ,
{
code : code ,
@ -609,14 +606,14 @@ PEG.Compiler = {
var expressionResultVar = PEG . Compiler . generateUniqueIdentifier ( "result" ) ;
return PEG . Compiler . formatCode (
"var ${savedPosVar} = this._ pos;",
"var ${savedPosVar} = pos;",
"var ${savedReportMatchFailuresVar} = context.reportMatchFailures;" ,
"context.reportMatchFailures = false;" ,
"${expressionCode}" ,
"context.reportMatchFailures = ${savedReportMatchFailuresVar};" ,
"if (${expressionResultVar} !== null) {" ,
" var ${resultVar} = '';" ,
" this._ pos = ${savedPosVar};",
" pos = ${savedPosVar};",
"} else {" ,
" var ${resultVar} = null;" ,
"}" ,
@ -636,7 +633,7 @@ PEG.Compiler = {
var expressionResultVar = PEG . Compiler . generateUniqueIdentifier ( "result" ) ;
return PEG . Compiler . formatCode (
"var ${savedPosVar} = this._ pos;",
"var ${savedPosVar} = pos;",
"var ${savedReportMatchFailuresVar} = context.reportMatchFailures;" ,
"context.reportMatchFailures = false;" ,
"${expressionCode}" ,
@ -645,7 +642,7 @@ PEG.Compiler = {
" var ${resultVar} = '';" ,
"} else {" ,
" var ${resultVar} = null;" ,
" this._ pos = ${savedPosVar};",
" pos = ${savedPosVar};",
"}" ,
{
expressionCode : PEG . Compiler . compileNode ( node . expression , expressionResultVar ) ,
@ -761,9 +758,9 @@ PEG.Compiler = {
rule _ref : function ( node , resultVar ) {
return PEG . Compiler . formatCode (
"var ${resultVar} = this. ${ruleMethod}(context);",
"var ${resultVar} = ${ruleMethod}(context);",
{
ruleMethod : " _ parse_" + node . name ,
ruleMethod : " parse_" + node . name ,
resultVar : resultVar
}
) ;
@ -771,13 +768,13 @@ PEG.Compiler = {
literal : function ( node , resultVar ) {
return PEG . Compiler . formatCode (
"if ( this._ input.substr(this._ pos, ${length}) === ${value|string}) {",
"if ( input.substr(pos, ${length}) === ${value|string}) {",
" var ${resultVar} = ${value|string};" ,
" this._ pos += ${length};",
" pos += ${length};",
"} else {" ,
" var ${resultVar} = null;" ,
" if (context.reportMatchFailures) {" ,
" this._ matchFailed(this._ quoteString(${value|string}));",
" matchFailed(quoteString(${value|string}));",
" }" ,
"}" ,
{
@ -790,13 +787,13 @@ PEG.Compiler = {
any : function ( node , resultVar ) {
return PEG . Compiler . formatCode (
"if ( this._ input.length > this._ pos) {",
" var ${resultVar} = this._ input.charAt(this._ pos);",
" this._ pos++;",
"if ( input.length > pos) {",
" var ${resultVar} = input.charAt(pos);",
" pos++;",
"} else {" ,
" var ${resultVar} = null;" ,
" if (context.reportMatchFailures) {" ,
" this._ matchFailed('any character');",
" matchFailed('any character');",
" }" ,
"}" ,
{ resultVar : resultVar }
@ -824,13 +821,13 @@ PEG.Compiler = {
}
return PEG . Compiler . formatCode (
"if ( this._ input.substr(this._ pos).match(${regexp}) !== null) {",
" var ${resultVar} = this._ input.charAt(this._ pos);",
" this._ pos++;",
"if ( input.substr(pos).match(${regexp}) !== null) {",
" var ${resultVar} = input.charAt(pos);",
" pos++;",
"} else {" ,
" var ${resultVar} = null;" ,
" if (context.reportMatchFailures) {" ,
" this._ matchFailed(${rawText|string});",
" matchFailed(${rawText|string});",
" }" ,
"}" ,
{
@ -884,56 +881,6 @@ PEG.Compiler = {
" /* Generated by PEG.js (http://pegjs.majda.cz/). */" ,
" " ,
" var result = {" ,
/* This needs to be in sync with PEG.StringUtils.quote. */
" _quoteString: 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" ,
" + '\"';" ,
" }," ,
" " ,
/* This needs to be in sync with PEG.ArrayUtils.contains. */
" _arrayContains: function(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;" ,
" }," ,
" " ,
" _matchFailed: function(failure) {" ,
" if (this._pos < this._rightmostMatchFailuresPos) {" ,
" return;" ,
" }" ,
" " ,
" if (this._pos > this._rightmostMatchFailuresPos) {" ,
" this._rightmostMatchFailuresPos = this._pos;" ,
" this._rightmostMatchFailuresExpected = [];" ,
" }" ,
" " ,
" if (!this._arrayContains(this._rightmostMatchFailuresExpected, failure)) {" ,
" this._rightmostMatchFailuresExpected.push(failure);" ,
" }" ,
" }," ,
" " ,
" ${parseFunctionDefinitions}" ,
" " ,
" /*" ,
" * Parses the input with a generated parser. If the parsing is successfull," ,
" * returns a value explicitly or implicitly specified by the grammar from" ,
@ -941,16 +888,61 @@ PEG.Compiler = {
" * unsuccessful, throws |PEG.grammarParser.SyntaxError| describing the error." ,
" */" ,
" parse: function(input) {" ,
" var that = this;" ,
" var pos = 0;" ,
" var rightmostMatchFailuresPos = 0;" ,
" var rightmostMatchFailuresExpected = [];" ,
" var cache = {};" ,
" " ,
/* This needs to be in sync with PEG.StringUtils.quote. */
" 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" ,
" + '\"';" ,
" }" ,
" " ,
/* This needs to be in sync with PEG.ArrayUtils.contains. */
" 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 initialize() {" ,
" that._input = input;" ,
" that._pos = 0;" ,
" that._rightmostMatchFailuresPos = 0;" ,
" that._rightmostMatchFailuresExpected = [];" ,
" that._cache = {};" ,
" function matchFailed(failure) {" ,
" if (pos < rightmostMatchFailuresPos) {" ,
" return;" ,
" }" ,
" " ,
" if (pos > rightmostMatchFailuresPos) {" ,
" rightmostMatchFailuresPos = pos;" ,
" rightmostMatchFailuresExpected = [];" ,
" }" ,
" " ,
" if (!arrayContains(rightmostMatchFailuresExpected, failure)) {" ,
" rightmostMatchFailuresExpected.push(failure);" ,
" }" ,
" }" ,
" " ,
" ${parseFunctionDefinitions}" ,
" " ,
" function buildErrorMessage() {" ,
" function buildExpected(failuresExpected) {" ,
" switch (failuresExpected.length) {" ,
@ -966,10 +958,10 @@ PEG.Compiler = {
" }" ,
" }" ,
" " ,
" var expected = buildExpected( that._ rightmostMatchFailuresExpected);",
" var pos = Math.max(that._pos, that._ rightmostMatchFailuresPos);",
" var actual = pos < that._ input.length",
" ? that._quoteString(that._input.charAt(p os))",
" var expected = buildExpected( rightmostMatchFailuresExpected);",
" var actualPos = Math.max(pos, rightmostMatchFailuresPos);",
" var actual = actualPos < input.length",
" ? quoteString(input.charAt(actualP os))",
" : 'end of input';" ,
" " ,
" return 'Expected ' + expected + ' but ' + actual + ' found.';" ,
@ -983,13 +975,11 @@ PEG.Compiler = {
" * 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 < p os; i++) {",
" for (var i = 0; i < rightmostMatchFailuresP os; i++) {",
" var ch = input.charAt(i);" ,
" if (ch === '\\n') {" ,
" if (!seenCR) { line++; }" ,
@ -1008,13 +998,11 @@ PEG.Compiler = {
" return { line: line, column: column };" ,
" }" ,
" " ,
" initialize();" ,
" " ,
" var initialContext = {" ,
" reportMatchFailures: true" ,
" };" ,
" " ,
" var result = this._ parse_${startRule}(initialContext);",
" var result = parse_${startRule}(initialContext);",
" " ,
" /*" ,
" * The parser is now in one of the following three states:" ,
@ -1022,27 +1010,28 @@ PEG.Compiler = {
" * 1. The parser successfully parsed the whole input." ,
" *" ,
" * - |result !== null|" ,
" * - | that._ pos === input.length|",
" * - | that._ rightmostMatchFailuresExpected.length| may or may not contain",
" * - | pos === input.length|",
" * - | rightmostMatchFailuresExpected.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._ rightmostMatchFailuresExpected.length| may or may not contain",
" * - | pos < input.length|",
" * - | rightmostMatchFailuresExpected.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._rightmostMatchFailuresExpected.length| contains at least one failure" ,
" * - |pos === 0|" ,
" * - |rightmostMatchFailuresExpected.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) {",
" if (result === null || pos !== input.length) {",
" var errorPosition = computeErrorPosition();" ,
" throw new this.SyntaxError(" ,
" buildErrorMessage()," ,