From ee00a1ae6ade63bce007e3849cbe6c7ef4e0e72d Mon Sep 17 00:00:00 2001 From: felix Date: Tue, 12 Sep 2017 13:21:35 -0700 Subject: [PATCH] Check allowedStartRules exist. (#532) Fixes #524 --- lib/compiler/passes/report-undefined-rules.js | 11 ++++++++++- test/api/pegjs-api.spec.js | 6 ++++++ test/unit/compiler/passes/helpers.js | 6 ++++-- .../compiler/passes/report-undefined-rules.spec.js | 8 ++++++++ 4 files changed, 28 insertions(+), 3 deletions(-) diff --git a/lib/compiler/passes/report-undefined-rules.js b/lib/compiler/passes/report-undefined-rules.js index 0f5d941..4108432 100644 --- a/lib/compiler/passes/report-undefined-rules.js +++ b/lib/compiler/passes/report-undefined-rules.js @@ -5,7 +5,7 @@ let asts = require("../asts"); let visitor = require("../visitor"); // Checks that all referenced rules exist. -function reportUndefinedRules(ast) { +function reportUndefinedRules(ast, options) { let check = visitor.build({ rule_ref(node) { if (!asts.findRule(ast, node.name)) { @@ -18,6 +18,15 @@ function reportUndefinedRules(ast) { }); check(ast); + + if (options.allowedStartRules) { + options.allowedStartRules.forEach(rule => { + if (!asts.findRule(ast, rule)) { + throw new GrammarError( + "Start rule \"" + rule + "\" is not defined."); + } + }); + } } module.exports = reportUndefinedRules; diff --git a/test/api/pegjs-api.spec.js b/test/api/pegjs-api.spec.js index 75a4cbb..f06f28d 100644 --- a/test/api/pegjs-api.spec.js +++ b/test/api/pegjs-api.spec.js @@ -30,6 +30,12 @@ describe("PEG.js API", function() { "c = 'x'" ].join("\n"); + it("throws an error on missing rule", function() { + expect(() => peg.generate(grammar, { + allowedStartRules: ["missing"] + })).to.throw(); + }); + // The |allowedStartRules| option is implemented separately for each // optimization mode, so we need to test it in both. diff --git a/test/unit/compiler/passes/helpers.js b/test/unit/compiler/passes/helpers.js index 1eed9aa..0232b79 100644 --- a/test/unit/compiler/passes/helpers.js +++ b/test/unit/compiler/passes/helpers.js @@ -57,13 +57,15 @@ module.exports = function(chai, utils) { ); }); - Assertion.addMethod("reportError", function(grammar, props) { + Assertion.addMethod("reportError", function(grammar, props, options) { + options = options !== undefined ? options : {}; + let ast = parser.parse(grammar); let passed, result; try { - utils.flag(this, "object")(ast); + utils.flag(this, "object")(ast, options); passed = true; } catch (e) { result = e; diff --git a/test/unit/compiler/passes/report-undefined-rules.spec.js b/test/unit/compiler/passes/report-undefined-rules.spec.js index 5fc37f5..bfaa43a 100644 --- a/test/unit/compiler/passes/report-undefined-rules.spec.js +++ b/test/unit/compiler/passes/report-undefined-rules.spec.js @@ -18,4 +18,12 @@ describe("compiler pass |reportUndefinedRules|", function() { } }); }); + + it("checks allowedStartRules", function() { + expect(pass).to.reportError("start = 'a'", { + message: "Start rule \"missing\" is not defined." + }, { + allowedStartRules: ["missing"] + }); + }); });