diff --git a/lib/compiler/index.js b/lib/compiler/index.js
index 40c05f3..d3edda9 100644
--- a/lib/compiler/index.js
+++ b/lib/compiler/index.js
@@ -19,16 +19,17 @@ var compiler = {
*/
passes: {
check: {
- reportMissingRules: require("./passes/report-missing-rules"),
- reportLeftRecursion: require("./passes/report-left-recursion"),
- reportInfiniteLoops: require("./passes/report-infinite-loops")
+ reportMissingRules: require("./passes/report-missing-rules"),
+ reportDuplicateRules: require("./passes/report-duplicate-rules"),
+ reportLeftRecursion: require("./passes/report-left-recursion"),
+ reportInfiniteLoops: require("./passes/report-infinite-loops")
},
transform: {
- removeProxyRules: require("./passes/remove-proxy-rules")
+ removeProxyRules: require("./passes/remove-proxy-rules")
},
generate: {
- generateBytecode: require("./passes/generate-bytecode"),
- generateJS: require("./passes/generate-js")
+ generateBytecode: require("./passes/generate-bytecode"),
+ generateJS: require("./passes/generate-js")
}
},
diff --git a/lib/compiler/passes/report-duplicate-rules.js b/lib/compiler/passes/report-duplicate-rules.js
new file mode 100644
index 0000000..44cfa27
--- /dev/null
+++ b/lib/compiler/passes/report-duplicate-rules.js
@@ -0,0 +1,26 @@
+"use strict";
+
+var GrammarError = require("../../grammar-error"),
+ visitor = require("../visitor");
+
+/* Checks that each rule is defined only once. */
+function reportDuplicateRules(ast) {
+ var rules = {};
+
+ var check = visitor.build({
+ rule: function(node) {
+ if (rules.hasOwnProperty(node.name)) {
+ throw new GrammarError(
+ "Rule \"" + node.name + "\" is already defined.",
+ node.location
+ );
+ }
+
+ rules[node.name] = true;
+ }
+ });
+
+ check(ast);
+}
+
+module.exports = reportDuplicateRules;
diff --git a/package.json b/package.json
index 3f5d20d..032326f 100644
--- a/package.json
+++ b/package.json
@@ -31,6 +31,7 @@
"lib/compiler/passes/report-left-recursion.js",
"lib/compiler/passes/report-infinite-loops.js",
"lib/compiler/passes/report-missing-rules.js",
+ "lib/compiler/passes/report-duplicate-rules.js",
"lib/grammar-error.js",
"lib/parser.js",
"lib/peg.js",
diff --git a/spec/index.html b/spec/index.html
index db65963..d59581b 100644
--- a/spec/index.html
+++ b/spec/index.html
@@ -10,6 +10,7 @@
+
diff --git a/spec/unit/compiler/passes/report-duplicate-rules.spec.js b/spec/unit/compiler/passes/report-duplicate-rules.spec.js
new file mode 100644
index 0000000..a74554e
--- /dev/null
+++ b/spec/unit/compiler/passes/report-duplicate-rules.spec.js
@@ -0,0 +1,20 @@
+/* global peg */
+
+"use strict";
+
+describe("compiler pass |reportDuplicateRules|", function() {
+ var pass = peg.compiler.passes.check.reportDuplicateRules;
+
+ it("reports duplicate rules", function() {
+ expect(pass).toReportError([
+ 'start = "a"',
+ 'start = "b"'
+ ].join('\n'), {
+ message: 'Rule "start" is already defined.',
+ location: {
+ start: { offset: 12, line: 2, column: 1 },
+ end: { offset: 23, line: 2, column: 12 }
+ }
+ });
+ });
+});