9717dc3417
The new terminology is more precise and in line with commonly used programming languages. The change involves mainly renaming related compiler pass and files associated with it.
215 lines
6.9 KiB
JavaScript
215 lines
6.9 KiB
JavaScript
/* global peg */
|
|
|
|
"use strict";
|
|
|
|
describe("PEG.js API", function() {
|
|
describe("generate", function() {
|
|
it("generates a parser", function() {
|
|
var parser = peg.generate('start = "a"');
|
|
|
|
expect(typeof parser).toBe("object");
|
|
expect(parser.parse("a")).toBe("a");
|
|
});
|
|
|
|
it("throws an exception on syntax error", function() {
|
|
expect(function() { peg.generate('start = @'); }).toThrow();
|
|
});
|
|
|
|
it("throws an exception on semantic error", function() {
|
|
expect(function() { peg.generate('start = undefined'); }).toThrow();
|
|
});
|
|
|
|
describe("allowed start rules", function() {
|
|
var grammar = [
|
|
'a = "x"',
|
|
'b = "x"',
|
|
'c = "x"'
|
|
].join("\n");
|
|
|
|
/*
|
|
* The |allowedStartRules| option is implemented separately for each
|
|
* optimization mode, so we need to test it in both.
|
|
*/
|
|
|
|
describe("when optimizing for parsing speed", function() {
|
|
describe("when |allowedStartRules| is not set", function() {
|
|
it("generated parser can start only from the first rule", function() {
|
|
var parser = peg.generate(grammar, { optimize: "speed" });
|
|
|
|
expect(parser.parse("x", { startRule: "a" })).toBe("x");
|
|
expect(
|
|
function() { parser.parse("x", { startRule: "b" }); }
|
|
).toThrow();
|
|
expect(
|
|
function() { parser.parse("x", { startRule: "c" }); }
|
|
).toThrow();
|
|
});
|
|
});
|
|
|
|
describe("when |allowedStartRules| is set", function() {
|
|
it("generated parser can start only from specified rules", function() {
|
|
var parser = peg.generate(grammar, {
|
|
optimize: "speed",
|
|
allowedStartRules: ["b", "c"]
|
|
});
|
|
|
|
expect(
|
|
function() { parser.parse("x", { startRule: "a" }); }
|
|
).toThrow();
|
|
expect(parser.parse("x", { startRule: "b" })).toBe("x");
|
|
expect(parser.parse("x", { startRule: "c" })).toBe("x");
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("when optimizing for code size", function() {
|
|
describe("when |allowedStartRules| is not set", function() {
|
|
it("generated parser can start only from the first rule", function() {
|
|
var parser = peg.generate(grammar, { optimize: "size" });
|
|
|
|
expect(parser.parse("x", { startRule: "a" })).toBe("x");
|
|
expect(
|
|
function() { parser.parse("x", { startRule: "b" }); }
|
|
).toThrow();
|
|
expect(
|
|
function() { parser.parse("x", { startRule: "c" }); }
|
|
).toThrow();
|
|
});
|
|
});
|
|
|
|
describe("when |allowedStartRules| is set", function() {
|
|
it("generated parser can start only from specified rules", function() {
|
|
var parser = peg.generate(grammar, {
|
|
optimize: "size",
|
|
allowedStartRules: ["b", "c"]
|
|
});
|
|
|
|
expect(
|
|
function() { parser.parse("x", { startRule: "a" }); }
|
|
).toThrow();
|
|
expect(parser.parse("x", { startRule: "b" })).toBe("x");
|
|
expect(parser.parse("x", { startRule: "c" })).toBe("x");
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("intermediate results caching", function() {
|
|
var grammar = [
|
|
'{ var n = 0; }',
|
|
'start = (a "b") / (a "c") { return n; }',
|
|
'a = "a" { n++; }'
|
|
].join("\n");
|
|
|
|
describe("when |cache| is not set", function() {
|
|
it("generated parser doesn't cache intermediate parse results", function() {
|
|
var parser = peg.generate(grammar);
|
|
|
|
expect(parser.parse("ac")).toBe(2);
|
|
});
|
|
});
|
|
|
|
describe("when |cache| is set to |false|", function() {
|
|
it("generated parser doesn't cache intermediate parse results", function() {
|
|
var parser = peg.generate(grammar, { cache: false });
|
|
|
|
expect(parser.parse("ac")).toBe(2);
|
|
});
|
|
});
|
|
|
|
describe("when |cache| is set to |true|", function() {
|
|
it("generated parser caches intermediate parse results", function() {
|
|
var parser = peg.generate(grammar, { cache: true });
|
|
|
|
expect(parser.parse("ac")).toBe(1);
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("tracing", function() {
|
|
var grammar = 'start = "a"';
|
|
|
|
describe("when |trace| is not set", function() {
|
|
it("generated parser doesn't trace", function() {
|
|
var parser = peg.generate(grammar),
|
|
tracer = jasmine.createSpyObj("tracer", ["trace"]);
|
|
|
|
parser.parse("a", { tracer: tracer });
|
|
|
|
expect(tracer.trace).not.toHaveBeenCalled();
|
|
});
|
|
});
|
|
|
|
describe("when |trace| is set to |false|", function() {
|
|
it("generated parser doesn't trace", function() {
|
|
var parser = peg.generate(grammar, { trace: false }),
|
|
tracer = jasmine.createSpyObj("tracer", ["trace"]);
|
|
|
|
parser.parse("a", { tracer: tracer });
|
|
|
|
expect(tracer.trace).not.toHaveBeenCalled();
|
|
});
|
|
});
|
|
|
|
describe("when |trace| is set to |true|", function() {
|
|
it("generated parser traces", function() {
|
|
var parser = peg.generate(grammar, { trace: true }),
|
|
tracer = jasmine.createSpyObj("tracer", ["trace"]);
|
|
|
|
parser.parse("a", { tracer: tracer });
|
|
|
|
expect(tracer.trace).toHaveBeenCalled();
|
|
});
|
|
});
|
|
});
|
|
|
|
/*
|
|
* The |optimize| option isn't tested because there is no meaningful way to
|
|
* write the specs without turning this into a performance test.
|
|
*/
|
|
|
|
describe("output", function() {
|
|
var grammar = 'start = "a"';
|
|
|
|
describe("when |output| is not set", function() {
|
|
it("returns generated parser object", function() {
|
|
var parser = peg.generate(grammar);
|
|
|
|
expect(typeof parser).toBe("object");
|
|
expect(parser.parse("a")).toBe("a");
|
|
});
|
|
});
|
|
|
|
describe("when |output| is set to |\"parser\"|", function() {
|
|
it("returns generated parser object", function() {
|
|
var parser = peg.generate(grammar, { output: "parser" });
|
|
|
|
expect(typeof parser).toBe("object");
|
|
expect(parser.parse("a")).toBe("a");
|
|
});
|
|
});
|
|
|
|
describe("when |output| is set to |\"source\"|", function() {
|
|
it("returns generated parser source code", function() {
|
|
var source = peg.generate(grammar, { output: "source" });
|
|
|
|
expect(typeof source).toBe("string");
|
|
expect(eval(source).parse("a")).toBe("a");
|
|
});
|
|
});
|
|
});
|
|
|
|
/*
|
|
* The |format|, |exportVars|, and |dependencies| options are not tested
|
|
* becasue there is no meaningful way to thest their effects without turning
|
|
* this into an integration test.
|
|
*/
|
|
|
|
/* The |plugins| option is tested in plugin API specs. */
|
|
|
|
it("accepts custom options", function() {
|
|
peg.generate('start = "a"', { foo: 42 });
|
|
});
|
|
});
|
|
});
|