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.
redux
David Majda 8 years ago
parent 999cc7be74
commit 8639cf6d61

@ -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',

Loading…
Cancel
Save