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,13 +881,25 @@ PEG.Compiler = {
" /* Generated by PEG.js (http://pegjs.majda.cz/). */", " /* Generated by PEG.js (http://pegjs.majda.cz/). */",
" ", " ",
" var result = {", " 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 = {};",
" ",
/* This needs to be in sync with PEG.StringUtils.quote. */ /* This needs to be in sync with PEG.StringUtils.quote. */
" _quoteString: function(s) {", " function quoteString(s) {",
" /*", " /*",
" * ECMA-262, 5th ed., 7.8.4: All characters may appear literally in a string", " * ECMA-262, 5th ed., 7.8.4: All characters may appear literally in a",
" * literal except for the closing quote character, backslash, carriage", " * string literal except for the closing quote character, backslash,",
" * return, line separator, paragraph separator, and line feed. Any character", " * carriage return, line separator, paragraph separator, and line feed.",
" * may appear in the form of an escape sequence.", " * Any character may appear in the form of an escape sequence.",
" */", " */",
" return '\"' + s", " return '\"' + s",
" .replace(/\\\\/g, '\\\\\\\\') // backslash", " .replace(/\\\\/g, '\\\\\\\\') // backslash",
@ -900,13 +909,13 @@ PEG.Compiler = {
" .replace(/\\u2029/g, '\\\\u2029') // paragraph separator", " .replace(/\\u2029/g, '\\\\u2029') // paragraph separator",
" .replace(/\\n/g, '\\\\n') // line feed", " .replace(/\\n/g, '\\\\n') // line feed",
" + '\"';", " + '\"';",
" },", " }",
" ", " ",
/* This needs to be in sync with PEG.ArrayUtils.contains. */ /* This needs to be in sync with PEG.ArrayUtils.contains. */
" _arrayContains: function(array, value) {", " function arrayContains(array, value) {",
" /*", " /*",
" * Stupid IE does not have Array.prototype.indexOf, otherwise this function", " * Stupid IE does not have Array.prototype.indexOf, otherwise this",
" * would be a one-liner.", " * function would be a one-liner.",
" */", " */",
" var length = array.length;", " var length = array.length;",
" for (var i = 0; i < length; i++) {", " for (var i = 0; i < length; i++) {",
@ -915,42 +924,25 @@ PEG.Compiler = {
" }", " }",
" }", " }",
" return false;", " return false;",
" },", " }",
" ", " ",
" _matchFailed: function(failure) {", " function matchFailed(failure) {",
" if (this._pos < this._rightmostMatchFailuresPos) {", " if (pos < rightmostMatchFailuresPos) {",
" return;", " return;",
" }", " }",
" ", " ",
" if (this._pos > this._rightmostMatchFailuresPos) {", " if (pos > rightmostMatchFailuresPos) {",
" this._rightmostMatchFailuresPos = this._pos;", " rightmostMatchFailuresPos = pos;",
" this._rightmostMatchFailuresExpected = [];", " rightmostMatchFailuresExpected = [];",
" }", " }",
" ", " ",
" if (!this._arrayContains(this._rightmostMatchFailuresExpected, failure)) {", " if (!arrayContains(rightmostMatchFailuresExpected, failure)) {",
" this._rightmostMatchFailuresExpected.push(failure);", " rightmostMatchFailuresExpected.push(failure);",
" }",
" }", " }",
" },",
" ", " ",
" ${parseFunctionDefinitions}", " ${parseFunctionDefinitions}",
" ", " ",
" /*",
" * 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 that = this;",
" ",
" function initialize() {",
" that._input = input;",
" that._pos = 0;",
" that._rightmostMatchFailuresPos = 0;",
" that._rightmostMatchFailuresExpected = [];",
" that._cache = {};",
" }",
" ",
" 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