From eaca5f0acf97b66ef141fed84aa95d4e72e33757 Mon Sep 17 00:00:00 2001 From: David Majda Date: Mon, 6 Apr 2015 10:34:07 +0200 Subject: [PATCH] Add location information to |GrammarError| This means all errors thrown by |PEG.buildParser| now have associated location information. --- lib/compiler/passes/report-infinite-loops.js | 4 ++-- lib/compiler/passes/report-left-recursion.js | 3 ++- lib/compiler/passes/report-missing-rules.js | 3 ++- lib/grammar-error.js | 3 ++- .../compiler/passes/report-infinite-loops.spec.js | 12 ++++++++++-- .../compiler/passes/report-left-recursion.spec.js | 12 ++++++++++-- .../compiler/passes/report-missing-rules.spec.js | 6 +++++- 7 files changed, 33 insertions(+), 10 deletions(-) diff --git a/lib/compiler/passes/report-infinite-loops.js b/lib/compiler/passes/report-infinite-loops.js index bfe87b6..7809271 100644 --- a/lib/compiler/passes/report-infinite-loops.js +++ b/lib/compiler/passes/report-infinite-loops.js @@ -10,13 +10,13 @@ function reportInfiniteLoops(ast) { var check = visitor.build({ zero_or_more: function(node) { if (asts.matchesEmpty(ast, node.expression)) { - throw new GrammarError("Infinite loop detected."); + throw new GrammarError("Infinite loop detected.", node.location); } }, one_or_more: function(node) { if (asts.matchesEmpty(ast, node.expression)) { - throw new GrammarError("Infinite loop detected."); + throw new GrammarError("Infinite loop detected.", node.location); } } }); diff --git a/lib/compiler/passes/report-left-recursion.js b/lib/compiler/passes/report-left-recursion.js index 774f1a3..0ec244d 100644 --- a/lib/compiler/passes/report-left-recursion.js +++ b/lib/compiler/passes/report-left-recursion.js @@ -34,7 +34,8 @@ function reportLeftRecursion(ast) { rule_ref: function(node, visitedRules) { if (arrays.contains(visitedRules, node.name)) { throw new GrammarError( - "Left recursion detected for rule \"" + node.name + "\"." + "Left recursion detected for rule \"" + node.name + "\".", + node.location ); } diff --git a/lib/compiler/passes/report-missing-rules.js b/lib/compiler/passes/report-missing-rules.js index 417e414..67f0908 100644 --- a/lib/compiler/passes/report-missing-rules.js +++ b/lib/compiler/passes/report-missing-rules.js @@ -8,7 +8,8 @@ function reportMissingRules(ast) { rule_ref: function(node) { if (!asts.findRule(ast, node.name)) { throw new GrammarError( - "Referenced rule \"" + node.name + "\" does not exist." + "Referenced rule \"" + node.name + "\" does not exist.", + node.location ); } } diff --git a/lib/grammar-error.js b/lib/grammar-error.js index 7497490..753aedc 100644 --- a/lib/grammar-error.js +++ b/lib/grammar-error.js @@ -1,9 +1,10 @@ var classes = require("./utils/classes"); /* Thrown when the grammar contains an error. */ -function GrammarError(message) { +function GrammarError(message, location) { this.name = "GrammarError"; this.message = message; + this.location = location; } classes.subclass(GrammarError, Error); diff --git a/spec/unit/compiler/passes/report-infinite-loops.spec.js b/spec/unit/compiler/passes/report-infinite-loops.spec.js index 8e8c11a..db973fa 100644 --- a/spec/unit/compiler/passes/report-infinite-loops.spec.js +++ b/spec/unit/compiler/passes/report-infinite-loops.spec.js @@ -3,13 +3,21 @@ describe("compiler pass |reportLeftRecursion|", function() { it("reports infinite loops for zero_or_more", function() { expect(pass).toReportError('start = ("")*', { - message: "Infinite loop detected." + message: "Infinite loop detected.", + location: { + start: { offset: 8, line: 1, column: 9 }, + end: { offset: 13, line: 1, column: 14 } + } }); }); it("reports infinite loops for one_or_more", function() { expect(pass).toReportError('start = ("")+', { - message: "Infinite loop detected." + message: "Infinite loop detected.", + location: { + start: { offset: 8, line: 1, column: 9 }, + end: { offset: 13, line: 1, column: 14 } + } }); }); diff --git a/spec/unit/compiler/passes/report-left-recursion.spec.js b/spec/unit/compiler/passes/report-left-recursion.spec.js index 5a85ee8..77b654c 100644 --- a/spec/unit/compiler/passes/report-left-recursion.spec.js +++ b/spec/unit/compiler/passes/report-left-recursion.spec.js @@ -3,7 +3,11 @@ describe("compiler pass |reportLeftRecursion|", function() { it("reports direct left recursion", function() { expect(pass).toReportError('start = start', { - message: 'Left recursion detected for rule \"start\".' + message: 'Left recursion detected for rule \"start\".', + location: { + start: { offset: 8, line: 1, column: 9 }, + end: { offset: 13, line: 1, column: 14 } + } }); }); @@ -12,7 +16,11 @@ describe("compiler pass |reportLeftRecursion|", function() { 'start = stop', 'stop = start' ].join("\n"), { - message: 'Left recursion detected for rule \"start\".' + message: 'Left recursion detected for rule \"start\".', + location: { + start: { offset: 21, line: 2, column: 9 }, + end: { offset: 26, line: 2, column: 14 } + } }); }); diff --git a/spec/unit/compiler/passes/report-missing-rules.spec.js b/spec/unit/compiler/passes/report-missing-rules.spec.js index f24b660..e0b50db 100644 --- a/spec/unit/compiler/passes/report-missing-rules.spec.js +++ b/spec/unit/compiler/passes/report-missing-rules.spec.js @@ -3,7 +3,11 @@ describe("compiler pass |reportMissingRules|", function() { it("reports missing rules", function() { expect(pass).toReportError('start = missing', { - message: 'Referenced rule "missing" does not exist.' + message: 'Referenced rule "missing" does not exist.', + location: { + start: { offset: 8, line: 1, column: 9 }, + end: { offset: 15, line: 1, column: 16 } + } }); }); });