Expose the parser object in action/predicate code

The action/predicate code didn't have access to the parser object. This
was mostly a side effect actions/predicates being implemented as nested
functions, in which |this| is a reference to the global object (an ugly
JavaScript quirk). The initializer, being implemented differently, had
access to the parser object via |this|, but this was not documented.

Because having access to the parser object can be useful, this commits
introduces a new |parser| variable which holds a reference to it, is
visible in action/predicate/initializer code, and is properly
documented.

See also:

  https://groups.google.com/forum/#!topic/pegjs/Na7YWnz6Bmg
redux
David Majda 10 years ago
parent c7521fb868
commit 39084496ca

@ -186,9 +186,10 @@ Rules can be preceded by an *initializer* — a piece of JavaScript code in curl
braces (“{” and “}”). This code is executed before the generated parser starts braces (“{” and “}”). This code is executed before the generated parser starts
parsing. All variables and functions defined in the initializer are accessible parsing. All variables and functions defined in the initializer are accessible
in rule actions and semantic predicates. The code inside the initializer can in rule actions and semantic predicates. The code inside the initializer can
access options passed to the parser using the `options` variable. Curly braces access the parser object using the `parser` variable and options passed to the
in the initializer code must be balanced. Let's look at the example grammar parser using the `options` variable. Curly braces in the initializer code must
from above using a simple initializer. be balanced. Let's look at the example grammar from above using a simple
initializer.
{ {
function makeInteger(o) { function makeInteger(o) {
@ -321,8 +322,8 @@ the `offset` function. It returns a zero-based character index into the input
string. The code can also access the current line and column using the `line` string. The code can also access the current line and column using the `line`
and `column` functions. Both return one-based indexes. and `column` functions. Both return one-based indexes.
The code inside the predicate can also access options passed to the parser using The code inside the predicate can also access the parser object using the
the `options` variable. `parser` variable and options passed to the parser using the `options` variable.
Note that curly braces in the predicate code must be balanced. Note that curly braces in the predicate code must be balanced.
@ -343,8 +344,8 @@ the `offset` function. It returns a zero-based character index into the input
string. The code can also access the current line and column using the `line` string. The code can also access the current line and column using the `line`
and `column` functions. Both return one-based indexes. and `column` functions. Both return one-based indexes.
The code inside the predicate can also access options passed to the parser using The code inside the predicate can also access the parser object using the
the `options` variable. `parser` variable and options passed to the parser using the `options` variable.
Note that curly braces in the predicate code must be balanced. Note that curly braces in the predicate code must be balanced.
@ -398,8 +399,8 @@ character index into the input string. The code can also access the line and
column at the beginning of the action's expression using the `line` and `column` column at the beginning of the action's expression using the `line` and `column`
functions. Both return one-based indexes. functions. Both return one-based indexes.
The code inside the action can also access options passed to the parser using The code inside the action can also access the parser object using the `parser`
the `options` variable. variable and options passed to the parser using the `options` variable.
Note that curly braces in the action code must be balanced. Note that curly braces in the action code must be balanced.

@ -692,6 +692,7 @@ module.exports = function(ast, options) {
'', '',
' function peg$parse(input) {', ' function peg$parse(input) {',
' var options = arguments.length > 1 ? arguments[1] : {},', ' var options = arguments.length > 1 ? arguments[1] : {},',
' parser = this,',
'', '',
' peg$FAILED = {},', ' peg$FAILED = {},',
'' ''

@ -26,6 +26,7 @@ module.exports = (function() {
function peg$parse(input) { function peg$parse(input) {
var options = arguments.length > 1 ? arguments[1] : {}, var options = arguments.length > 1 ? arguments[1] : {},
parser = this,
peg$FAILED = {}, peg$FAILED = {},

@ -211,6 +211,15 @@ describe("generated parser", function() {
expect(parser).toParse("a", [1, 1]); expect(parser).toParse("a", [1, 1]);
}); });
it("can use the |parser| variable to access the parser object", function() {
var parser = PEG.buildParser([
'{ var result = parser; }',
'start = "a" { return result; }'
].join("\n"), options);
expect(parser).toParse("a", parser);
});
it("can use options passed to the parser", function() { it("can use options passed to the parser", function() {
var parser = PEG.buildParser([ var parser = PEG.buildParser([
'{ var result = options; }', '{ var result = options; }',
@ -382,6 +391,15 @@ describe("generated parser", function() {
expect(parser).toParse("a", 42); expect(parser).toParse("a", 42);
}); });
it("can use the |parser| variable to access the parser object", function() {
var parser = PEG.buildParser(
'start = "a" { return parser; }',
options
);
expect(parser).toParse("a", parser);
});
it("can use options passed to the parser", function() { it("can use options passed to the parser", function() {
var parser = PEG.buildParser( var parser = PEG.buildParser(
'start = "a" { return options; }', 'start = "a" { return options; }',
@ -546,6 +564,15 @@ describe("generated parser", function() {
expect(parser).toParse("a", ["a", undefined]); expect(parser).toParse("a", ["a", undefined]);
}); });
it("can use the |parser| variable to access the parser object", function() {
var parser = PEG.buildParser([
'{ var result; }',
'start = "a" &{ result = parser; return true; } { return result; }'
].join("\n"), options);
expect(parser).toParse("a", parser);
});
it("can use options passed to the parser", function() { it("can use options passed to the parser", function() {
var parser = PEG.buildParser([ var parser = PEG.buildParser([
'{ var result; }', '{ var result; }',
@ -637,6 +664,15 @@ describe("generated parser", function() {
expect(parser).toParse("a", ["a", undefined]); expect(parser).toParse("a", ["a", undefined]);
}); });
it("can use the |parser| variable to access the parser object", function() {
var parser = PEG.buildParser([
'{ var result; }',
'start = "a" !{ result = parser; return false; } { return result; }'
].join("\n"), options);
expect(parser).toParse("a", parser);
});
it("can use options passed to the parser", function() { it("can use options passed to the parser", function() {
var parser = PEG.buildParser([ var parser = PEG.buildParser([
'{ var result; }', '{ var result; }',

Loading…
Cancel
Save