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 15 years ago
parent a1dcd245bb
commit e3aa4df090

@ -43,6 +43,20 @@ PEG.buildParser = function(grammar, startRule) {
/* Array manipulation utility functions. */
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
* PEG.Grammar.Action.prototype.compile.
@ -194,6 +208,10 @@ PEG.Grammar.Any = function() {};
PEG.Grammar.Sequence = function(elements) { this._elements = elements; };
PEG.Grammar.Sequence.prototype = {
getElements: function() { return this._elements; }
};
PEG.Grammar.Choice = function(alternatives) {
this._alternatives = alternatives;
};
@ -991,28 +1009,34 @@ PEG.Grammar.RuleRef.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
* 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
? "apply"
: "call";

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

@ -61,6 +61,21 @@ global.doesNotParseWithPos = function(parser, input, line, column) {
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() {
ok(!PEG.ArrayUtils.contains([], 42));

Loading…
Cancel
Save