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 15 years ago
parent 1daf1448e5
commit 439c815e48

@ -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(pos))",
" 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.';",
@ -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 < pos; i++) {",
" for (var i = 0; i < rightmostMatchFailuresPos; 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(),",

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