Changed action parameter processing to avoid the arguments object.

The action now computes the number of passed parameters during the code
generation and the parameters are declared directly as $1, $2, etc. in the
generated function.

This does not speed up the benchmark suite execution statistically significantly
on V8.

Detailed results (benchmark suite totals):

---------------------------------
 Test #     Before       After
---------------------------------
      1   28.68 kB/s   29.08 kB/s
      2   28.77 kB/s   28.72 kB/s
      3   28.89 kB/s   28.78 kB/s
      4   28.84 kB/s   28.57 kB/s
      5   28.86 kB/s   28.84 kB/s
---------------------------------
Average   28.81 kB/s   28.80 kB/s
---------------------------------

Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/533.2 (KHTML, like Gecko) Chrome/5.0.342.9 Safari/533.2
redux
David Majda 14 years ago
parent a1dcd245bb
commit e3aa4df090

@ -43,6 +43,20 @@ PEG.buildParser = function(grammar, startRule) {
/* Array manipulation utility functions. */ /* Array manipulation utility functions. */
PEG.ArrayUtils = { PEG.ArrayUtils = {
/* Like Python's |range|, but without |step|. */
range: function(start, stop) {
if (stop === undefined) {
stop = start;
start = 0;
}
var result = new Array(Math.max(0, stop - start));
for (var i = 0, j = start; j < stop; i++, j++) {
result[i] = j;
}
return result;
},
/* /*
* The code needs to be in sync with a code template in * The code needs to be in sync with a code template in
* PEG.Grammar.Action.prototype.compile. * PEG.Grammar.Action.prototype.compile.
@ -194,6 +208,10 @@ PEG.Grammar.Any = function() {};
PEG.Grammar.Sequence = function(elements) { this._elements = elements; }; PEG.Grammar.Sequence = function(elements) { this._elements = elements; };
PEG.Grammar.Sequence.prototype = {
getElements: function() { return this._elements; }
};
PEG.Grammar.Choice = function(alternatives) { PEG.Grammar.Choice = function(alternatives) {
this._alternatives = alternatives; this._alternatives = alternatives;
}; };
@ -991,28 +1009,34 @@ PEG.Grammar.RuleRef.prototype.compile = function(resultVar) {
}; };
PEG.Grammar.Action.prototype.compile = function(resultVar) { PEG.Grammar.Action.prototype.compile = function(resultVar) {
var expressionResultVar = PEG.Compiler.generateUniqueIdentifier("result");
var actionCode = this._action.replace(
/\$(\d+)/g,
function(match, digits) {
return PEG.Compiler.formatCode(
"(arguments[${index}])",
{ index: parseInt(digits) - 1 }
);
}
)
var actionFunction = PEG.Compiler.formatCode(
"function() { ${actionCode} }",
{ actionCode: actionCode }
);
/* /*
* In case of sequences, we splat their elements into function arguments one * In case of sequences, we splat their elements into function arguments one
* by one. Example: * by one. Example:
* *
* start: "a" "b" "c" { alert(arguments.length) } // => "3" * start: "a" "b" "c" { alert(arguments.length) } // => 3
*
* This behavior is reflected in this function.
*/ */
var expressionResultVar = PEG.Compiler.generateUniqueIdentifier("result");
var paramCount = this._expression instanceof PEG.Grammar.Sequence
? this._expression.getElements().length
: 1;
var params = PEG.ArrayUtils.map(
PEG.ArrayUtils.range(1, paramCount + 1),
function(n) { return "$" + n; }
).join(", ");
var actionFunction = PEG.Compiler.formatCode(
"function(${params}) { ${action} }",
{
params: params,
action: this._action
}
);
var invokeFunctionName = this._expression instanceof PEG.Grammar.Sequence var invokeFunctionName = this._expression instanceof PEG.Grammar.Sequence
? "apply" ? "apply"
: "call"; : "call";

@ -81,9 +81,9 @@ PEG.grammarParser = (function(){
this._pos = savedPos0; this._pos = savedPos0;
} }
var result0 = result1 !== null var result0 = result1 !== null
? (function() { ? (function($1, $2) {
var result = {}; var result = {};
PEG.ArrayUtils.each((arguments[1]), function(rule) { result[rule.getName()] = rule; }); PEG.ArrayUtils.each($2, function(rule) { result[rule.getName()] = rule; });
return result; return result;
}).apply(this, result1) }).apply(this, result1)
: null; : null;
@ -153,8 +153,8 @@ PEG.grammarParser = (function(){
this._pos = savedPos1; this._pos = savedPos1;
} }
var result5 = result6 !== null var result5 = result6 !== null
? (function() { ? (function($1, $2, $3, $4) {
return new PEG.Grammar.Rule((arguments[0]), (arguments[1]) !== "" ? (arguments[1]) : null, (arguments[3])); return new PEG.Grammar.Rule($1, $2 !== "" ? $2 : null, $4);
}).apply(this, result6) }).apply(this, result6)
: null; : null;
@ -246,13 +246,13 @@ PEG.grammarParser = (function(){
this._pos = savedPos2; this._pos = savedPos2;
} }
var result14 = result15 !== null var result14 = result15 !== null
? (function() { ? (function($1, $2) {
return (arguments[1]).length > 0 return $2.length > 0
? new PEG.Grammar.Choice([(arguments[0])].concat(PEG.ArrayUtils.map( ? new PEG.Grammar.Choice([$1].concat(PEG.ArrayUtils.map(
(arguments[1]), $2,
function(element) { return element[1]; } function(element) { return element[1]; }
))) )))
: (arguments[0]); : $1;
}).apply(this, result15) }).apply(this, result15)
: null; : null;
@ -296,10 +296,10 @@ PEG.grammarParser = (function(){
this._pos = savedPos4; this._pos = savedPos4;
} }
var result25 = result26 !== null var result25 = result26 !== null
? (function() { ? (function($1, $2) {
return new PEG.Grammar.Action( return new PEG.Grammar.Action(
(arguments[0]).length != 1 ? new PEG.Grammar.Sequence((arguments[0])) : (arguments[0])[0], $1.length != 1 ? new PEG.Grammar.Sequence($1) : $1[0],
(arguments[1]) $2
); );
}).apply(this, result26) }).apply(this, result26)
: null; : null;
@ -313,7 +313,7 @@ PEG.grammarParser = (function(){
var result24 = this._parse_prefixed(context); var result24 = this._parse_prefixed(context);
} }
var result22 = result23 !== null var result22 = result23 !== null
? (function() { return (arguments[0]).length != 1 ? new PEG.Grammar.Sequence((arguments[0])) : (arguments[0])[0]; }).call(this, result23) ? (function($1) { return $1.length != 1 ? new PEG.Grammar.Sequence($1) : $1[0]; }).call(this, result23)
: null; : null;
if (result22 !== null) { if (result22 !== null) {
var result21 = result22; var result21 = result22;
@ -357,7 +357,7 @@ PEG.grammarParser = (function(){
this._pos = savedPos6; this._pos = savedPos6;
} }
var result36 = result37 !== null var result36 = result37 !== null
? (function() { return new PEG.Grammar.AndPredicate((arguments[1])); }).apply(this, result37) ? (function($1, $2) { return new PEG.Grammar.AndPredicate($2); }).apply(this, result37)
: null; : null;
if (result36 !== null) { if (result36 !== null) {
var result30 = result36; var result30 = result36;
@ -377,7 +377,7 @@ PEG.grammarParser = (function(){
this._pos = savedPos5; this._pos = savedPos5;
} }
var result32 = result33 !== null var result32 = result33 !== null
? (function() { return new PEG.Grammar.NotPredicate((arguments[1])); }).apply(this, result33) ? (function($1, $2) { return new PEG.Grammar.NotPredicate($2); }).apply(this, result33)
: null; : null;
if (result32 !== null) { if (result32 !== null) {
var result30 = result32; var result30 = result32;
@ -426,7 +426,7 @@ PEG.grammarParser = (function(){
this._pos = savedPos9; this._pos = savedPos9;
} }
var result50 = result51 !== null var result50 = result51 !== null
? (function() { return new PEG.Grammar.Optional((arguments[0])); }).apply(this, result51) ? (function($1, $2) { return new PEG.Grammar.Optional($1); }).apply(this, result51)
: null; : null;
if (result50 !== null) { if (result50 !== null) {
var result40 = result50; var result40 = result50;
@ -446,7 +446,7 @@ PEG.grammarParser = (function(){
this._pos = savedPos8; this._pos = savedPos8;
} }
var result46 = result47 !== null var result46 = result47 !== null
? (function() { return new PEG.Grammar.ZeroOrMore((arguments[0])); }).apply(this, result47) ? (function($1, $2) { return new PEG.Grammar.ZeroOrMore($1); }).apply(this, result47)
: null; : null;
if (result46 !== null) { if (result46 !== null) {
var result40 = result46; var result40 = result46;
@ -466,7 +466,7 @@ PEG.grammarParser = (function(){
this._pos = savedPos7; this._pos = savedPos7;
} }
var result42 = result43 !== null var result42 = result43 !== null
? (function() { return new PEG.Grammar.OneOrMore((arguments[0])); }).apply(this, result43) ? (function($1, $2) { return new PEG.Grammar.OneOrMore($1); }).apply(this, result43)
: null; : null;
if (result42 !== null) { if (result42 !== null) {
var result40 = result42; var result40 = result42;
@ -557,28 +557,28 @@ PEG.grammarParser = (function(){
this._pos = savedPos11; this._pos = savedPos11;
} }
var result66 = result67 !== null var result66 = result67 !== null
? (function() { return new PEG.Grammar.RuleRef((arguments[0])); }).apply(this, result67) ? (function($1, $2) { return new PEG.Grammar.RuleRef($1); }).apply(this, result67)
: null; : null;
if (result66 !== null) { if (result66 !== null) {
var result54 = result66; var result54 = result66;
} else { } else {
var result65 = this._parse_literal(context); var result65 = this._parse_literal(context);
var result64 = result65 !== null var result64 = result65 !== null
? (function() { return new PEG.Grammar.Literal((arguments[0])); }).call(this, result65) ? (function($1) { return new PEG.Grammar.Literal($1); }).call(this, result65)
: null; : null;
if (result64 !== null) { if (result64 !== null) {
var result54 = result64; var result54 = result64;
} else { } else {
var result63 = this._parse_dot(context); var result63 = this._parse_dot(context);
var result62 = result63 !== null var result62 = result63 !== null
? (function() { return new PEG.Grammar.Any(); }).call(this, result63) ? (function($1) { return new PEG.Grammar.Any(); }).call(this, result63)
: null; : null;
if (result62 !== null) { if (result62 !== null) {
var result54 = result62; var result54 = result62;
} else { } else {
var result61 = this._parse_class(context); var result61 = this._parse_class(context);
var result60 = result61 !== null var result60 = result61 !== null
? (function() { return new PEG.Grammar.Class((arguments[0])); }).call(this, result61) ? (function($1) { return new PEG.Grammar.Class($1); }).call(this, result61)
: null; : null;
if (result60 !== null) { if (result60 !== null) {
var result54 = result60; var result54 = result60;
@ -604,7 +604,7 @@ PEG.grammarParser = (function(){
this._pos = savedPos10; this._pos = savedPos10;
} }
var result55 = result56 !== null var result55 = result56 !== null
? (function() { return (arguments[1]); }).apply(this, result56) ? (function($1, $2, $3) { return $2; }).apply(this, result56)
: null; : null;
if (result55 !== null) { if (result55 !== null) {
var result54 = result55; var result54 = result55;
@ -652,7 +652,7 @@ PEG.grammarParser = (function(){
this._pos = savedPos14; this._pos = savedPos14;
} }
var result75 = result76 !== null var result75 = result76 !== null
? (function() { return (arguments[0]).substr(1, (arguments[0]).length - 2); }).apply(this, result76) ? (function($1, $2) { return $1.substr(1, $1.length - 2); }).apply(this, result76)
: null; : null;
context.reportMatchFailures = savedReportMatchFailures; context.reportMatchFailures = savedReportMatchFailures;
if (context.reportMatchFailures && result75 === null) { if (context.reportMatchFailures && result75 === null) {
@ -739,7 +739,7 @@ PEG.grammarParser = (function(){
this._pos = savedPos15; this._pos = savedPos15;
} }
var result79 = result80 !== null var result79 = result80 !== null
? (function() { return (arguments[0]) + (arguments[1]).join("") + (arguments[2]); }).apply(this, result80) ? (function($1, $2, $3) { return $1 + $2.join("") + $3; }).apply(this, result80)
: null; : null;
@ -773,7 +773,7 @@ PEG.grammarParser = (function(){
var result88 = null; var result88 = null;
} }
var result87 = result88 !== null var result87 = result88 !== null
? (function() { return (arguments[0]).join(""); }).call(this, result88) ? (function($1) { return $1.join(""); }).call(this, result88)
: null; : null;
@ -806,7 +806,7 @@ PEG.grammarParser = (function(){
} }
} }
var result90 = result91 !== null var result90 = result91 !== null
? (function() { return (arguments[0]); }).call(this, result91) ? (function($1) { return $1; }).call(this, result91)
: null; : null;
@ -852,7 +852,7 @@ PEG.grammarParser = (function(){
this._pos = savedPos16; this._pos = savedPos16;
} }
var result92 = result93 !== null var result92 = result93 !== null
? (function() { return (arguments[0]); }).apply(this, result93) ? (function($1, $2) { return $1; }).apply(this, result93)
: null; : null;
@ -898,7 +898,7 @@ PEG.grammarParser = (function(){
this._pos = savedPos17; this._pos = savedPos17;
} }
var result96 = result97 !== null var result96 = result97 !== null
? (function() { return (arguments[0]); }).apply(this, result97) ? (function($1, $2) { return $1; }).apply(this, result97)
: null; : null;
@ -944,7 +944,7 @@ PEG.grammarParser = (function(){
this._pos = savedPos18; this._pos = savedPos18;
} }
var result100 = result101 !== null var result100 = result101 !== null
? (function() { return (arguments[0]); }).apply(this, result101) ? (function($1, $2) { return $1; }).apply(this, result101)
: null; : null;
@ -990,7 +990,7 @@ PEG.grammarParser = (function(){
this._pos = savedPos19; this._pos = savedPos19;
} }
var result104 = result105 !== null var result104 = result105 !== null
? (function() { return (arguments[0]); }).apply(this, result105) ? (function($1, $2) { return $1; }).apply(this, result105)
: null; : null;
@ -1036,7 +1036,7 @@ PEG.grammarParser = (function(){
this._pos = savedPos20; this._pos = savedPos20;
} }
var result108 = result109 !== null var result108 = result109 !== null
? (function() { return (arguments[0]); }).apply(this, result109) ? (function($1, $2) { return $1; }).apply(this, result109)
: null; : null;
@ -1082,7 +1082,7 @@ PEG.grammarParser = (function(){
this._pos = savedPos21; this._pos = savedPos21;
} }
var result112 = result113 !== null var result112 = result113 !== null
? (function() { return (arguments[0]); }).apply(this, result113) ? (function($1, $2) { return $1; }).apply(this, result113)
: null; : null;
@ -1128,7 +1128,7 @@ PEG.grammarParser = (function(){
this._pos = savedPos22; this._pos = savedPos22;
} }
var result116 = result117 !== null var result116 = result117 !== null
? (function() { return (arguments[0]); }).apply(this, result117) ? (function($1, $2) { return $1; }).apply(this, result117)
: null; : null;
@ -1174,7 +1174,7 @@ PEG.grammarParser = (function(){
this._pos = savedPos23; this._pos = savedPos23;
} }
var result120 = result121 !== null var result120 = result121 !== null
? (function() { return (arguments[0]); }).apply(this, result121) ? (function($1, $2) { return $1; }).apply(this, result121)
: null; : null;
@ -1220,7 +1220,7 @@ PEG.grammarParser = (function(){
this._pos = savedPos24; this._pos = savedPos24;
} }
var result124 = result125 !== null var result124 = result125 !== null
? (function() { return (arguments[0]); }).apply(this, result125) ? (function($1, $2) { return $1; }).apply(this, result125)
: null; : null;
@ -1266,7 +1266,7 @@ PEG.grammarParser = (function(){
this._pos = savedPos25; this._pos = savedPos25;
} }
var result128 = result129 !== null var result128 = result129 !== null
? (function() { return (arguments[0]); }).apply(this, result129) ? (function($1, $2) { return $1; }).apply(this, result129)
: null; : null;
@ -1419,8 +1419,8 @@ PEG.grammarParser = (function(){
this._pos = savedPos26; this._pos = savedPos26;
} }
var result132 = result133 !== null var result132 = result133 !== null
? (function() { ? (function($1, $2, $3) {
return (arguments[0]) + (arguments[1]).join(""); return $1 + $2.join("");
}).apply(this, result133) }).apply(this, result133)
: null; : null;
context.reportMatchFailures = savedReportMatchFailures; context.reportMatchFailures = savedReportMatchFailures;
@ -1472,7 +1472,7 @@ PEG.grammarParser = (function(){
this._pos = savedPos27; this._pos = savedPos27;
} }
var result145 = result146 !== null var result145 = result146 !== null
? (function() { return (arguments[0]); }).apply(this, result146) ? (function($1, $2) { return $1; }).apply(this, result146)
: null; : null;
context.reportMatchFailures = savedReportMatchFailures; context.reportMatchFailures = savedReportMatchFailures;
if (context.reportMatchFailures && result145 === null) { if (context.reportMatchFailures && result145 === null) {
@ -1539,7 +1539,7 @@ PEG.grammarParser = (function(){
this._pos = savedPos28; this._pos = savedPos28;
} }
var result151 = result152 !== null var result151 = result152 !== null
? (function() { return (arguments[1]).join(""); }).apply(this, result152) ? (function($1, $2, $3) { return $2.join(""); }).apply(this, result152)
: null; : null;
@ -1678,7 +1678,7 @@ PEG.grammarParser = (function(){
this._pos = savedPos29; this._pos = savedPos29;
} }
var result164 = result165 !== null var result164 = result165 !== null
? (function() { return (arguments[1]); }).apply(this, result165) ? (function($1, $2) { return $2; }).apply(this, result165)
: null; : null;
@ -1743,7 +1743,7 @@ PEG.grammarParser = (function(){
this._pos = savedPos31; this._pos = savedPos31;
} }
var result172 = result173 !== null var result172 = result173 !== null
? (function() { return (arguments[1]).join(""); }).apply(this, result173) ? (function($1, $2, $3) { return $2.join(""); }).apply(this, result173)
: null; : null;
@ -1882,7 +1882,7 @@ PEG.grammarParser = (function(){
this._pos = savedPos32; this._pos = savedPos32;
} }
var result185 = result186 !== null var result185 = result186 !== null
? (function() { return (arguments[1]); }).apply(this, result186) ? (function($1, $2) { return $2; }).apply(this, result186)
: null; : null;
@ -1989,8 +1989,8 @@ PEG.grammarParser = (function(){
this._pos = savedPos34; this._pos = savedPos34;
} }
var result193 = result194 !== null var result193 = result194 !== null
? (function() { ? (function($1, $2, $3, $4, $5) {
return (arguments[1]) + (arguments[2]).join(""); return $2 + $3.join("");
}).apply(this, result194) }).apply(this, result194)
: null; : null;
context.reportMatchFailures = savedReportMatchFailures; context.reportMatchFailures = savedReportMatchFailures;
@ -2045,20 +2045,20 @@ PEG.grammarParser = (function(){
this._pos = savedPos35; this._pos = savedPos35;
} }
var result204 = result205 !== null var result204 = result205 !== null
? (function() { ? (function($1, $2, $3) {
if ((arguments[0]).charCodeAt(0) > (arguments[2]).charCodeAt(0)) { if ($1.charCodeAt(0) > $3.charCodeAt(0)) {
throw new this.SyntaxError( throw new this.SyntaxError(
"Invalid character range: " "Invalid character range: "
+ PEG.RegExpUtils.quoteForClass((arguments[0])) + PEG.RegExpUtils.quoteForClass($1)
+ "-" + "-"
+ PEG.RegExpUtils.quoteForClass((arguments[2])) + PEG.RegExpUtils.quoteForClass($3)
+ "." + "."
); );
} }
return PEG.RegExpUtils.quoteForClass((arguments[0])) return PEG.RegExpUtils.quoteForClass($1)
+ "-" + "-"
+ PEG.RegExpUtils.quoteForClass((arguments[2])); + PEG.RegExpUtils.quoteForClass($3);
}).apply(this, result205) }).apply(this, result205)
: null; : null;
@ -2084,8 +2084,8 @@ PEG.grammarParser = (function(){
var result210 = this._parse_bracketDelimitedCharacter(context); var result210 = this._parse_bracketDelimitedCharacter(context);
var result209 = result210 !== null var result209 = result210 !== null
? (function() { ? (function($1) {
return PEG.RegExpUtils.quoteForClass((arguments[0])); return PEG.RegExpUtils.quoteForClass($1);
}).call(this, result210) }).call(this, result210)
: null; : null;
@ -2225,7 +2225,7 @@ PEG.grammarParser = (function(){
this._pos = savedPos36; this._pos = savedPos36;
} }
var result218 = result219 !== null var result218 = result219 !== null
? (function() { return (arguments[1]); }).apply(this, result219) ? (function($1, $2) { return $2; }).apply(this, result219)
: null; : null;
@ -2331,8 +2331,8 @@ PEG.grammarParser = (function(){
this._pos = savedPos38; this._pos = savedPos38;
} }
var result226 = result227 !== null var result226 = result227 !== null
? (function() { ? (function($1, $2, $3) {
return (arguments[2]) return $3
.replace("b", "\b") .replace("b", "\b")
.replace("f", "\f") .replace("f", "\f")
.replace("n", "\n") .replace("n", "\n")
@ -2395,7 +2395,7 @@ PEG.grammarParser = (function(){
this._pos = savedPos40; this._pos = savedPos40;
} }
var result236 = result237 !== null var result236 = result237 !== null
? (function() { return "\0"; }).apply(this, result237) ? (function($1, $2) { return "\0"; }).apply(this, result237)
: null; : null;
@ -2447,8 +2447,8 @@ PEG.grammarParser = (function(){
this._pos = savedPos42; this._pos = savedPos42;
} }
var result241 = result242 !== null var result241 = result242 !== null
? (function() { ? (function($1, $2, $3) {
return String.fromCharCode(parseInt("0x" + (arguments[1]) + (arguments[2]))); return String.fromCharCode(parseInt("0x" + $2 + $3));
}).apply(this, result242) }).apply(this, result242)
: null; : null;
@ -2513,8 +2513,8 @@ PEG.grammarParser = (function(){
this._pos = savedPos43; this._pos = savedPos43;
} }
var result246 = result247 !== null var result246 = result247 !== null
? (function() { ? (function($1, $2, $3, $4, $5) {
return String.fromCharCode(parseInt("0x" + (arguments[1]) + (arguments[2]) + (arguments[3]) + (arguments[4]))); return String.fromCharCode(parseInt("0x" + $2 + $3 + $4 + $5));
}).apply(this, result247) }).apply(this, result247)
: null; : null;
@ -2561,7 +2561,7 @@ PEG.grammarParser = (function(){
this._pos = savedPos44; this._pos = savedPos44;
} }
var result253 = result254 !== null var result253 = result254 !== null
? (function() { return (arguments[1]); }).apply(this, result254) ? (function($1, $2) { return $2; }).apply(this, result254)
: null; : null;

@ -61,6 +61,21 @@ global.doesNotParseWithPos = function(parser, input, line, column) {
module("PEG.ArrayUtils"); module("PEG.ArrayUtils");
test("range", function() {
deepEqual(PEG.ArrayUtils.range(-1), []);
deepEqual(PEG.ArrayUtils.range(0), []);
deepEqual(PEG.ArrayUtils.range(1), [0]);
deepEqual(PEG.ArrayUtils.range(2), [0, 1]);
deepEqual(PEG.ArrayUtils.range(3), [0, 1, 2]);
deepEqual(PEG.ArrayUtils.range(0, -1), []);
deepEqual(PEG.ArrayUtils.range(0, 0), []);
deepEqual(PEG.ArrayUtils.range(0, 1), [0]);
deepEqual(PEG.ArrayUtils.range(0, 2), [0, 1]);
deepEqual(PEG.ArrayUtils.range(0, 3), [0, 1, 2]);
deepEqual(PEG.ArrayUtils.range(-3, 0), [-3, -2, -1]);
});
test("contains", function() { test("contains", function() {
ok(!PEG.ArrayUtils.contains([], 42)); ok(!PEG.ArrayUtils.contains([], 42));

Loading…
Cancel
Save