Move lot of stuff in generated parsers into the |parse| method

We want to have the rule parsing functions inside the |parse| method
because we want them to share a common environment. In the future,
initializers will be executed in this enviromnent and thus functions and
variables defined by them will be accessible to the rule parsing
functions.

Moving various private properties from the parser object into the
|parse| method was not strictly necessary, but it was a natural step
after moving the functions.
redux
David Majda 14 years ago
parent 1daf1448e5
commit 439c815e48

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

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save