diff --git a/README.md b/README.md index a46b4ab..59d7ed9 100644 --- a/README.md +++ b/README.md @@ -346,6 +346,9 @@ The code inside the action can access all variables and functions defined in the initializer at the beginning of the grammar. Curly braces in the action code must be balanced. +The code inside the action can also access the string matched by the expression +using the `text` function. + The code inside the action can also access the parse position at the beginning of the action's expression using the `offset` function. It returns a zero-based character index into the input string. The code can also access the line and diff --git a/lib/compiler/passes/generate-code.js b/lib/compiler/passes/generate-code.js index 5b6ec38..a858570 100644 --- a/lib/compiler/passes/generate-code.js +++ b/lib/compiler/passes/generate-code.js @@ -404,6 +404,10 @@ module.exports = function(ast, options) { ' return cachedReportedPosDetails;', ' }', ' ', + ' function text() {', + ' return input.substring(reportedPos, pos);', + ' }', + ' ', ' function offset() {', ' return reportedPos;', ' }', diff --git a/spec/generated-parser.spec.js b/spec/generated-parser.spec.js index 4a038e2..7c38a47 100644 --- a/spec/generated-parser.spec.js +++ b/spec/generated-parser.spec.js @@ -171,6 +171,33 @@ describe("generated parser", function() { expect(parser).toParse("a", 42); }); + it("can use the |text| function", function() { + var parser = PEG.buildParser([ + '{ var result = text(); }', + 'start = "a" { return result; }' + ].join("\n"), options); + + expect(parser).toParse("a", ""); + }); + + it("can use the |offset| function to get the current parse position", function() { + var parser = PEG.buildParser([ + '{ var result = offset(); }', + 'start = "a" { return result; }' + ].join("\n"), options); + + expect(parser).toParse("a", 0); + }); + + it("can use the |line| and |column| functions to get the current line and column", function() { + var parser = PEG.buildParser([ + '{ var result = [line(), column()]; }', + 'start = "a" { return result; }' + ].join("\n"), options); + + expect(parser).toParse("a", [1, 1]); + }); + it("can use options passed to the parser", function() { var parser = PEG.buildParser([ '{ var result = options; }', @@ -255,6 +282,15 @@ describe("generated parser", function() { expect(parser).toParse("a", "a"); }); + it("can use the |text| function to get the text matched by the expression", function() { + var parser = PEG.buildParser( + 'start = "a" "b" "c" { return text(); }', + options + ); + + expect(parser).toParse("abc", "abc"); + }); + it("can use the |offset| function to get the current parse position", function() { var parser = PEG.buildParser( 'start = "a" ("b" { return offset(); })', @@ -425,6 +461,15 @@ describe("generated parser", function() { expect(parser).toParse("a", ["a", ""]); }); + it("can use the |text| function", function() { + var parser = PEG.buildParser( + 'start = "a" &{ return text() === ""; }', + options + ); + + expect(parser).toParse("a", ["a", ""]); + }); + it("can use the |offset| function to get the current parse position", function() { var parser = PEG.buildParser( 'start = "a" &{ return offset() === 1; }', @@ -507,6 +552,15 @@ describe("generated parser", function() { expect(parser).toParse("a", ["a", ""]); }); + it("can use the |text| function", function() { + var parser = PEG.buildParser( + 'start = "a" !{ return text() !== ""; }', + options + ); + + expect(parser).toParse("a", ["a", ""]); + }); + it("can use the |offset| function to get the current parse position", function() { var parser = PEG.buildParser( 'start = "a" !{ return offset() !== 1; }',