You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
pegjs/spec/api/plugin-api.spec.js

157 lines
4.5 KiB
JavaScript

"use strict";
let peg = require("../../lib/peg");
describe("plugin API", function() {
beforeEach(function() {
this.addMatchers({
toBeObject: function() {
this.message = () =>
"Expected " + jasmine.pp(this.actual) + " "
+ (this.isNot ? "not " : "")
+ "to be an object.";
return this.actual !== null && typeof this.actual === "object";
},
toBeArray: function() {
this.message = () =>
"Expected " + jasmine.pp(this.actual) + " "
+ (this.isNot ? "not " : "")
+ "to be an array.";
return Object.prototype.toString.apply(this.actual) === "[object Array]";
},
toBeFunction: function() {
this.message = () =>
"Expected " + jasmine.pp(this.actual) + " "
+ (this.isNot ? "not " : "")
+ "to be a function.";
return typeof this.actual === "function";
}
});
});
describe("use", function() {
let grammar = 'start = "a"';
it("is called for each plugin", function() {
let pluginsUsed = [false, false, false],
plugins = [
{ use: function() { pluginsUsed[0] = true; } },
{ use: function() { pluginsUsed[1] = true; } },
{ use: function() { pluginsUsed[2] = true; } }
];
peg.generate(grammar, { plugins: plugins });
expect(pluginsUsed).toEqual([true, true, true]);
});
it("receives configuration", function() {
let plugin = {
use: function(config) {
expect(config).toBeObject();
expect(config.parser).toBeObject();
expect(config.parser.parse('start = "a"')).toBeObject();
expect(config.passes).toBeObject();
expect(config.passes.check).toBeArray();
config.passes.check.forEach(pass => {
expect(pass).toBeFunction();
});
expect(config.passes.transform).toBeArray();
config.passes.transform.forEach(pass => {
expect(pass).toBeFunction();
});
expect(config.passes.generate).toBeArray();
config.passes.generate.forEach(pass => {
expect(pass).toBeFunction();
});
}
};
peg.generate(grammar, { plugins: [plugin] });
});
it("receives options", function() {
let plugin = {
use: function(config, options) {
expect(options).toEqual(generateOptions);
}
},
generateOptions = { plugins: [plugin], foo: 42 };
peg.generate(grammar, generateOptions);
});
it("can replace parser", function() {
let plugin = {
use: function(config) {
let parser = peg.generate([
'start = .* {',
' return {',
' type: "grammar",',
' rules: [',
' {',
' type: "rule",',
' name: "start",',
' expression: { type: "literal", value: text(), ignoreCase: false }',
' }',
' ]',
' };',
'}'
].join("\n"));
config.parser = parser;
}
},
parser = peg.generate('a', { plugins: [plugin] });
expect(parser.parse("a")).toBe("a");
});
it("can change compiler passes", function() {
let plugin = {
use: function(config) {
let pass = ast => {
ast.code = '({ parse: function() { return 42; } })';
};
config.passes.generate = [pass];
}
},
parser = peg.generate(grammar, { plugins: [plugin] });
expect(parser.parse("a")).toBe(42);
});
it("can change options", function() {
let grammar = [
'a = "x"',
'b = "x"',
'c = "x"'
].join("\n"),
plugin = {
use: function(config, options) {
options.allowedStartRules = ["b", "c"];
}
},
parser = peg.generate(grammar, {
allowedStartRules: ["a"],
plugins: [plugin]
});
expect(() => { parser.parse("x", { startRule: "a" }); }).toThrow();
expect(parser.parse("x", { startRule: "b" })).toBe("x");
expect(parser.parse("x", { startRule: "c" })).toBe("x");
});
});
});