From 8639cf6d61acf410a1e2f4b49c980ac674b1571e Mon Sep 17 00:00:00 2001 From: David Majda Date: Fri, 17 Jun 2016 15:45:00 +0200 Subject: [PATCH] Expectation refactoring 6/7: Move "buildMessage" to SyntaxError The "buildMessage" utility function, which was previously internal, is now exposed as SyntaxError.buildMessage in generated parsers. The motivation behind this is two-fold: 1. Building of a syntax error message is a responsibility of the SyntaxError class, meaning the code should be placed there. 2. By exposing the message building code, parser users can use it to generate customized error messages without duplicating PEG.js's code. Note that helper functions inside "buildMessage" ("describeExpected", "describeFound", etc.) currently aren't exposed. They may become exposed in the future if there is enough demand. --- lib/compiler/passes/generate-js.js | 202 ++++++++++++++--------------- 1 file changed, 101 insertions(+), 101 deletions(-) diff --git a/lib/compiler/passes/generate-js.js b/lib/compiler/passes/generate-js.js index 301dc0f..3f9b5e3 100644 --- a/lib/compiler/passes/generate-js.js +++ b/lib/compiler/passes/generate-js.js @@ -781,6 +781,106 @@ function generateJS(ast, options) { '}', '', 'peg$subclass(peg$SyntaxError, Error);', + '', + 'peg$SyntaxError.buildMessage = function(expected, found) {', + ' var DESCRIBE_EXPECTATION_FNS = {', + ' literal: function(expectation) {', + ' return "\\\"" + literalEscape(expectation.text) + "\\\"";', + ' },', + '', + ' class: function(expectation) {', + ' var escapedParts = "",', + ' i;', + '', + ' for (i = 0; i < expectation.parts.length; i++) {', + ' escapedParts += expectation.parts[i] instanceof Array', + ' ? classEscape(expectation.parts[i][0]) + "-" + classEscape(expectation.parts[i][1])', + ' : classEscape(expectation.parts[i]);', + ' }', + '', + ' return "[" + (expectation.inverted ? "^" : "") + escapedParts + "]";', + ' },', + '', + ' any: function(expectation) {', + ' return "any character";', + ' },', + '', + ' end: function(expectation) {', + ' return "end of input";', + ' },', + '', + ' other: function(expectation) {', + ' return expectation.description;', + ' }', + ' };', + '', + ' function hex(ch) {', + ' return ch.charCodeAt(0).toString(16).toUpperCase();', + ' }', + '', + ' function literalEscape(s) {', + ' return s', + ' .replace(/\\\\/g, \'\\\\\\\\\')', // backslash + ' .replace(/"/g, \'\\\\"\')', // closing double quote + ' .replace(/\\0/g, \'\\\\0\')', // null + ' .replace(/\\t/g, \'\\\\t\')', // horizontal tab + ' .replace(/\\n/g, \'\\\\n\')', // line feed + ' .replace(/\\r/g, \'\\\\r\')', // carriage return + ' .replace(/[\\x00-\\x0F]/g, function(ch) { return \'\\\\x0\' + hex(ch); })', + ' .replace(/[\\x10-\\x1F\\x7F-\\x9F]/g, function(ch) { return \'\\\\x\' + hex(ch); });', + ' }', + '', + ' function classEscape(s) {', + ' return s', + ' .replace(/\\\\/g, \'\\\\\\\\\')', // backslash + ' .replace(/\\]/g, \'\\\\]\')', // closing bracket + ' .replace(/\\^/g, \'\\\\^\')', // caret + ' .replace(/-/g, \'\\\\-\')', // dash + ' .replace(/\\0/g, \'\\\\0\')', // null + ' .replace(/\\t/g, \'\\\\t\')', // horizontal tab + ' .replace(/\\n/g, \'\\\\n\')', // line feed + ' .replace(/\\r/g, \'\\\\r\')', // carriage return + ' .replace(/[\\x00-\\x0F]/g, function(ch) { return \'\\\\x0\' + hex(ch); })', + ' .replace(/[\\x10-\\x1F\\x7F-\\x9F]/g, function(ch) { return \'\\\\x\' + hex(ch); });', + ' }', + '', + ' function describeExpectation(expectation) {', + ' return DESCRIBE_EXPECTATION_FNS[expectation.type](expectation);', + ' }', + '', + ' function describeExpected(expected) {', + ' var descriptions = new Array(expected.length),', + ' i, j;', + '', + ' for (i = 0; i < expected.length; i++) {', + ' descriptions[i] = describeExpectation(expected[i]);', + ' }', + '', + ' descriptions.sort();', + '', + ' if (descriptions.length > 0) {', + ' for (i = 1, j = 1; i < descriptions.length; i++) {', + ' if (descriptions[i - 1] !== descriptions[i]) {', + ' descriptions[j] = descriptions[i];', + ' j++;', + ' }', + ' }', + ' descriptions.length = j;', + ' }', + '', + ' return descriptions.length > 1', + ' ? descriptions.slice(0, -1).join(", ")', + ' + " or "', + ' + descriptions[descriptions.length - 1]', + ' : descriptions[0];', + ' }', + '', + ' function describeFound(found) {', + ' return found ? "\\"" + literalEscape(found) + "\\"" : "end of input";', + ' }', + '', + ' return "Expected " + describeExpected(expected) + " but " + describeFound(found) + " found.";', + '};', '' ].join('\n')); @@ -1045,108 +1145,8 @@ function generateJS(ast, options) { ' }', '', ' function peg$buildException(message, expected, found, location) {', - ' function buildMessage(expected, found) {', - ' var DESCRIBE_EXPECTATION_FNS = {', - ' literal: function(expectation) {', - ' return "\\\"" + literalEscape(expectation.text) + "\\\"";', - ' },', - '', - ' class: function(expectation) {', - ' var escapedParts = "",', - ' i;', - '', - ' for (i = 0; i < expectation.parts.length; i++) {', - ' escapedParts += expectation.parts[i] instanceof Array', - ' ? classEscape(expectation.parts[i][0]) + "-" + classEscape(expectation.parts[i][1])', - ' : classEscape(expectation.parts[i]);', - ' }', - '', - ' return "[" + (expectation.inverted ? "^" : "") + escapedParts + "]";', - ' },', - '', - ' any: function(expectation) {', - ' return "any character";', - ' },', - '', - ' end: function(expectation) {', - ' return "end of input";', - ' },', - '', - ' other: function(expectation) {', - ' return expectation.description;', - ' }', - ' };', - '', - ' function hex(ch) {', - ' return ch.charCodeAt(0).toString(16).toUpperCase();', - ' }', - '', - ' function literalEscape(s) {', - ' return s', - ' .replace(/\\\\/g, \'\\\\\\\\\')', // backslash - ' .replace(/"/g, \'\\\\"\')', // closing double quote - ' .replace(/\\0/g, \'\\\\0\')', // null - ' .replace(/\\t/g, \'\\\\t\')', // horizontal tab - ' .replace(/\\n/g, \'\\\\n\')', // line feed - ' .replace(/\\r/g, \'\\\\r\')', // carriage return - ' .replace(/[\\x00-\\x0F]/g, function(ch) { return \'\\\\x0\' + hex(ch); })', - ' .replace(/[\\x10-\\x1F\\x7F-\\x9F]/g, function(ch) { return \'\\\\x\' + hex(ch); });', - ' }', - '', - ' function classEscape(s) {', - ' return s', - ' .replace(/\\\\/g, \'\\\\\\\\\')', // backslash - ' .replace(/\\]/g, \'\\\\]\')', // closing bracket - ' .replace(/\\^/g, \'\\\\^\')', // caret - ' .replace(/-/g, \'\\\\-\')', // dash - ' .replace(/\\0/g, \'\\\\0\')', // null - ' .replace(/\\t/g, \'\\\\t\')', // horizontal tab - ' .replace(/\\n/g, \'\\\\n\')', // line feed - ' .replace(/\\r/g, \'\\\\r\')', // carriage return - ' .replace(/[\\x00-\\x0F]/g, function(ch) { return \'\\\\x0\' + hex(ch); })', - ' .replace(/[\\x10-\\x1F\\x7F-\\x9F]/g, function(ch) { return \'\\\\x\' + hex(ch); });', - ' }', - '', - ' function describeExpectation(expectation) {', - ' return DESCRIBE_EXPECTATION_FNS[expectation.type](expectation);', - ' }', - '', - ' function describeExpected(expected) {', - ' var descriptions = new Array(expected.length),', - ' i, j;', - '', - ' for (i = 0; i < expected.length; i++) {', - ' descriptions[i] = describeExpectation(expected[i]);', - ' }', - '', - ' descriptions.sort();', - '', - ' if (descriptions.length > 0) {', - ' for (i = 1, j = 1; i < descriptions.length; i++) {', - ' if (descriptions[i - 1] !== descriptions[i]) {', - ' descriptions[j] = descriptions[i];', - ' j++;', - ' }', - ' }', - ' descriptions.length = j;', - ' }', - '', - ' return descriptions.length > 1', - ' ? descriptions.slice(0, -1).join(", ")', - ' + " or "', - ' + descriptions[descriptions.length - 1]', - ' : descriptions[0];', - ' }', - '', - ' function describeFound(found) {', - ' return found ? "\\"" + literalEscape(found) + "\\"" : "end of input";', - ' }', - '', - ' return "Expected " + describeExpected(expected) + " but " + describeFound(found) + " found.";', - ' }', - '', ' return new peg$SyntaxError(', - ' message !== null ? message : buildMessage(expected, found),', + ' message !== null ? message : peg$SyntaxError.buildMessage(expected, found),', ' expected,', ' found,', ' location',