From e9d8dc8ebaeda081a6617bb261733bf1a18f2152 Mon Sep 17 00:00:00 2001 From: David Majda Date: Sat, 11 Feb 2012 15:44:24 +0100 Subject: [PATCH] More responsibility for building an error message into |SyntaxError| --- src/emitter.js | 74 +++++++++++++++++++++++++++----------------------- src/parser.js | 74 +++++++++++++++++++++++++++----------------------- 2 files changed, 80 insertions(+), 68 deletions(-) diff --git a/src/emitter.js b/src/emitter.js index f588356..5e20589 100644 --- a/src/emitter.js +++ b/src/emitter.js @@ -344,38 +344,19 @@ PEG.compiler.emitter = function(ast) { ' #block definition', ' ', ' #end', - ' function buildErrorMessage() {', - ' function buildExpected(failuresExpected) {', - ' failuresExpected.sort();', - ' ', - ' var lastFailure = null;', - ' var failuresExpectedUnique = [];', - ' for (var i = 0; i < failuresExpected.length; i++) {', - ' if (failuresExpected[i] !== lastFailure) {', - ' failuresExpectedUnique.push(failuresExpected[i]);', - ' lastFailure = failuresExpected[i];', - ' }', - ' }', - ' ', - ' switch (failuresExpectedUnique.length) {', - ' case 0:', - ' return "end of input";', - ' case 1:', - ' return failuresExpectedUnique[0];', - ' default:', - ' return failuresExpectedUnique.slice(0, failuresExpectedUnique.length - 1).join(", ")', - ' + " or "', - ' + failuresExpectedUnique[failuresExpectedUnique.length - 1];', + ' ', + ' function cleanupExpected(expected) {', + ' expected.sort();', + ' ', + ' var lastExpected = null;', + ' var cleanExpected = [];', + ' for (var i = 0; i < expected.length; i++) {', + ' if (expected[i] !== lastExpected) {', + ' cleanExpected.push(expected[i]);', + ' lastExpected = expected[i];', ' }', ' }', - ' ', - ' var expected = buildExpected(rightmostFailuresExpected);', - ' var actualPos = Math.max(pos, rightmostFailuresPos);', - ' var actual = actualPos < input.length', - ' ? quote(input.charAt(actualPos))', - ' : "end of input";', - ' ', - ' return "Expected " + expected + " but " + actual + " found.";', + ' return cleanExpected;', ' }', ' ', ' function computeErrorPosition() {', @@ -440,10 +421,14 @@ PEG.compiler.emitter = function(ast) { ' * handle these states.', ' */', ' if (result === null || pos !== input.length) {', + ' var offset = Math.max(pos, rightmostFailuresPos);', + ' var found = offset < input.length ? input.charAt(offset) : null;', ' var errorPosition = computeErrorPosition();', + ' ', ' throw new this.SyntaxError(', - ' buildErrorMessage(),', - ' Math.max(pos, rightmostFailuresPos),', + ' cleanupExpected(rightmostFailuresExpected),', + ' found,', + ' offset,', ' errorPosition.line,', ' errorPosition.column', ' );', @@ -458,9 +443,30 @@ PEG.compiler.emitter = function(ast) { ' ', ' /* Thrown when a parser encounters a syntax error. */', ' ', - ' result.SyntaxError = function(message, offset, line, column) {', + ' result.SyntaxError = function(expected, found, offset, line, column) {', + ' function buildMessage(expected, found) {', + ' var expectedHumanized, foundHumanized;', + ' ', + ' switch (expected.length) {', + ' case 0:', + ' expectedHumanized = "end of input";', + ' break;', + ' case 1:', + ' expectedHumanized = expected[0];', + ' break;', + ' default:', + ' expectedHumanized = expected.slice(0, expected.length - 1).join(", ")', + ' + " or "', + ' + expected[expected.length - 1];', + ' }', + ' ', + ' foundHumanized = found ? quote(found) : "end of input";', + ' ', + ' return "Expected " + expectedHumanized + " but " + foundHumanized + " found.";', + ' }', + ' ', ' this.name = "SyntaxError";', - ' this.message = message;', + ' this.message = buildMessage(expected, found);', ' this.offset = offset;', ' this.line = line;', ' this.column = column;', diff --git a/src/parser.js b/src/parser.js index 91fe9d2..bc562cc 100644 --- a/src/parser.js +++ b/src/parser.js @@ -3502,38 +3502,19 @@ PEG.parser = (function(){ return result0; } - function buildErrorMessage() { - function buildExpected(failuresExpected) { - failuresExpected.sort(); - - var lastFailure = null; - var failuresExpectedUnique = []; - for (var i = 0; i < failuresExpected.length; i++) { - if (failuresExpected[i] !== lastFailure) { - failuresExpectedUnique.push(failuresExpected[i]); - lastFailure = failuresExpected[i]; - } - } - - switch (failuresExpectedUnique.length) { - case 0: - return "end of input"; - case 1: - return failuresExpectedUnique[0]; - default: - return failuresExpectedUnique.slice(0, failuresExpectedUnique.length - 1).join(", ") - + " or " - + failuresExpectedUnique[failuresExpectedUnique.length - 1]; + + function cleanupExpected(expected) { + expected.sort(); + + var lastExpected = null; + var cleanExpected = []; + for (var i = 0; i < expected.length; i++) { + if (expected[i] !== lastExpected) { + cleanExpected.push(expected[i]); + lastExpected = expected[i]; } } - - var expected = buildExpected(rightmostFailuresExpected); - var actualPos = Math.max(pos, rightmostFailuresPos); - var actual = actualPos < input.length - ? quote(input.charAt(actualPos)) - : "end of input"; - - return "Expected " + expected + " but " + actual + " found."; + return cleanExpected; } function computeErrorPosition() { @@ -3595,10 +3576,14 @@ PEG.parser = (function(){ * handle these states. */ if (result === null || pos !== input.length) { + var offset = Math.max(pos, rightmostFailuresPos); + var found = offset < input.length ? input.charAt(offset) : null; var errorPosition = computeErrorPosition(); + throw new this.SyntaxError( - buildErrorMessage(), - Math.max(pos, rightmostFailuresPos), + cleanupExpected(rightmostFailuresExpected), + found, + offset, errorPosition.line, errorPosition.column ); @@ -3613,9 +3598,30 @@ PEG.parser = (function(){ /* Thrown when a parser encounters a syntax error. */ - result.SyntaxError = function(message, offset, line, column) { + result.SyntaxError = function(expected, found, offset, line, column) { + function buildMessage(expected, found) { + var expectedHumanized, foundHumanized; + + switch (expected.length) { + case 0: + expectedHumanized = "end of input"; + break; + case 1: + expectedHumanized = expected[0]; + break; + default: + expectedHumanized = expected.slice(0, expected.length - 1).join(", ") + + " or " + + expected[expected.length - 1]; + } + + foundHumanized = found ? quote(found) : "end of input"; + + return "Expected " + expectedHumanized + " but " + foundHumanized + " found."; + } + this.name = "SyntaxError"; - this.message = message; + this.message = buildMessage(expected, found); this.offset = offset; this.line = line; this.column = column;