2016-09-22 16:23:24 +02:00
|
|
|
"use strict";
|
|
|
|
|
2016-09-08 13:29:06 +02:00
|
|
|
/* global console */
|
2015-06-08 20:21:19 +02:00
|
|
|
|
2016-12-08 08:59:04 +01:00
|
|
|
let chai = require("chai");
|
2016-09-08 16:04:36 +02:00
|
|
|
let peg = require("../../lib/peg");
|
2016-12-08 08:59:04 +01:00
|
|
|
let sinon = require("sinon");
|
|
|
|
|
|
|
|
let expect = chai.expect;
|
2016-09-08 13:29:06 +02:00
|
|
|
|
2014-05-23 15:07:22 +02:00
|
|
|
describe("generated parser API", function() {
|
|
|
|
describe("parse", function() {
|
|
|
|
it("parses input", function() {
|
2016-09-21 15:06:56 +02:00
|
|
|
let parser = peg.generate("start = 'a'");
|
2014-05-23 15:07:22 +02:00
|
|
|
|
2016-12-08 08:59:04 +01:00
|
|
|
expect(parser.parse("a")).to.equal("a");
|
2014-05-23 15:07:22 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
it("throws an exception on syntax error", function() {
|
2016-09-21 15:06:56 +02:00
|
|
|
let parser = peg.generate("start = 'a'");
|
2014-05-23 15:07:22 +02:00
|
|
|
|
2016-12-08 08:59:04 +01:00
|
|
|
expect(() => { parser.parse("b"); }).to.throw();
|
2014-05-23 15:07:22 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
describe("start rule", function() {
|
2016-09-08 16:04:36 +02:00
|
|
|
let parser = peg.generate([
|
2016-10-04 11:00:25 +02:00
|
|
|
"a = 'x' { return 'a'; }",
|
|
|
|
"b = 'x' { return 'b'; }",
|
|
|
|
"c = 'x' { return 'c'; }"
|
|
|
|
].join("\n"), { allowedStartRules: ["b", "c"] });
|
2014-05-23 15:07:22 +02:00
|
|
|
|
|
|
|
describe("when |startRule| is not set", function() {
|
|
|
|
it("starts parsing from the first allowed rule", function() {
|
2016-12-08 08:59:04 +01:00
|
|
|
expect(parser.parse("x")).to.equal("b");
|
2014-05-23 15:07:22 +02:00
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe("when |startRule| is set to an allowed rule", function() {
|
2014-12-05 15:33:29 +01:00
|
|
|
it("starts parsing from specified rule", function() {
|
2016-12-08 08:59:04 +01:00
|
|
|
expect(parser.parse("x", { startRule: "b" })).to.equal("b");
|
|
|
|
expect(parser.parse("x", { startRule: "c" })).to.equal("c");
|
2014-05-23 15:07:22 +02:00
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe("when |startRule| is set to a disallowed start rule", function() {
|
|
|
|
it("throws an exception", function() {
|
2016-12-08 08:59:04 +01:00
|
|
|
expect(() => { parser.parse("x", { startRule: "a" }); }).to.throw();
|
2014-05-23 15:07:22 +02:00
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2015-02-24 05:12:24 +01:00
|
|
|
describe("tracing", function() {
|
2016-09-08 16:04:36 +02:00
|
|
|
let parser = peg.generate([
|
2016-10-04 11:00:25 +02:00
|
|
|
"start = a / b",
|
|
|
|
"a = 'a'",
|
|
|
|
"b = 'b'"
|
|
|
|
].join("\n"), { trace: true });
|
2015-02-24 05:12:24 +01:00
|
|
|
|
|
|
|
describe("default tracer", function() {
|
2015-08-21 17:24:49 +02:00
|
|
|
it("traces using console.log (if console is defined)", function() {
|
2016-12-16 14:14:05 +01:00
|
|
|
let messages = [
|
|
|
|
"1:1-1:1 rule.enter start",
|
|
|
|
"1:1-1:1 rule.enter a",
|
|
|
|
"1:1-1:1 rule.fail a",
|
|
|
|
"1:1-1:1 rule.enter b",
|
|
|
|
"1:1-1:2 rule.match b",
|
|
|
|
"1:1-1:2 rule.match start"
|
|
|
|
];
|
|
|
|
|
2015-08-21 17:24:49 +02:00
|
|
|
if (typeof console === "object") {
|
2016-12-08 08:59:04 +01:00
|
|
|
sinon.stub(console, "log");
|
2015-08-21 17:24:49 +02:00
|
|
|
}
|
2015-02-24 05:12:24 +01:00
|
|
|
|
2016-12-08 08:59:04 +01:00
|
|
|
try {
|
|
|
|
parser.parse("b");
|
|
|
|
|
|
|
|
if (typeof console === "object") {
|
2016-12-16 14:18:02 +01:00
|
|
|
expect(console.log.callCount).to.equal(messages.length);
|
|
|
|
messages.forEach((message, index) => {
|
|
|
|
let call = console.log.getCall(index);
|
|
|
|
expect(call.calledWithExactly(message)).to.equal(true);
|
2016-12-16 14:14:05 +01:00
|
|
|
});
|
2016-12-08 08:59:04 +01:00
|
|
|
}
|
|
|
|
} finally {
|
|
|
|
if (typeof console === "object") {
|
|
|
|
console.log.restore();
|
|
|
|
}
|
2015-08-21 17:24:49 +02:00
|
|
|
}
|
2015-02-24 05:12:24 +01:00
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe("custom tracers", function() {
|
|
|
|
describe("trace", function() {
|
|
|
|
it("receives tracing events", function() {
|
2016-12-16 14:14:05 +01:00
|
|
|
let events = [
|
|
|
|
{
|
|
|
|
type: "rule.enter",
|
|
|
|
rule: "start",
|
|
|
|
location: {
|
|
|
|
start: { offset: 0, line: 1, column: 1 },
|
|
|
|
end: { offset: 0, line: 1, column: 1 }
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
type: "rule.enter",
|
|
|
|
rule: "a",
|
|
|
|
location: {
|
|
|
|
start: { offset: 0, line: 1, column: 1 },
|
|
|
|
end: { offset: 0, line: 1, column: 1 }
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
type: "rule.fail",
|
|
|
|
rule: "a",
|
|
|
|
location: {
|
|
|
|
start: { offset: 0, line: 1, column: 1 },
|
|
|
|
end: { offset: 0, line: 1, column: 1 }
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
type: "rule.enter",
|
|
|
|
rule: "b",
|
|
|
|
location: {
|
|
|
|
start: { offset: 0, line: 1, column: 1 },
|
|
|
|
end: { offset: 0, line: 1, column: 1 }
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
type: "rule.match",
|
|
|
|
rule: "b",
|
|
|
|
result: "b",
|
|
|
|
location: {
|
|
|
|
start: { offset: 0, line: 1, column: 1 },
|
|
|
|
end: { offset: 1, line: 1, column: 2 }
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
type: "rule.match",
|
|
|
|
rule: "start",
|
|
|
|
result: "b",
|
|
|
|
location: {
|
|
|
|
start: { offset: 0, line: 1, column: 1 },
|
|
|
|
end: { offset: 1, line: 1, column: 2 }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
];
|
|
|
|
|
2016-12-08 08:59:04 +01:00
|
|
|
let tracer = { trace: sinon.spy() };
|
2015-02-24 05:12:24 +01:00
|
|
|
|
|
|
|
parser.parse("b", { tracer: tracer });
|
|
|
|
|
2016-12-16 14:18:02 +01:00
|
|
|
expect(tracer.trace.callCount).to.equal(events.length);
|
|
|
|
events.forEach((event, index) => {
|
|
|
|
let call = tracer.trace.getCall(index);
|
|
|
|
expect(call.calledWithExactly(event)).to.equal(true);
|
2016-12-16 14:14:05 +01:00
|
|
|
});
|
2015-02-24 05:12:24 +01:00
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2014-05-23 15:07:22 +02:00
|
|
|
it("accepts custom options", function() {
|
2016-09-21 15:06:56 +02:00
|
|
|
let parser = peg.generate("start = 'a'");
|
2014-05-23 15:07:22 +02:00
|
|
|
|
|
|
|
parser.parse("a", { foo: 42 });
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|