Utility functions cleanup: Cleanup lib/compiler/javascript.js

redux
David Majda 10 years ago
parent c1e1502d43
commit 88e5f136e1

@ -1,53 +1,8 @@
function hex(ch) { return ch.charCodeAt(0).toString(16).toUpperCase(); }
/* JavaScript code generation helpers. */ /* JavaScript code generation helpers. */
var javascript = { var javascript = {
/* stringEscape: function(s) {
* Returns a string padded on the left to a desired length with a character.
*
* The code needs to be in sync with the code template in the compilation
* function for "action" nodes.
*/
padLeft: function(input, padding, length) {
var result = input;
var padLength = length - input.length;
for (var i = 0; i < padLength; i++) {
result = padding + result;
}
return result;
},
/*
* Returns an escape sequence for given character. Uses \x for characters <=
* 0xFF to save space, \u for the rest.
*
* The code needs to be in sync with the code template in the compilation
* function for "action" nodes.
*/
escape: function(ch) {
var charCode = ch.charCodeAt(0);
var escapeChar;
var length;
if (charCode <= 0xFF) {
escapeChar = 'x';
length = 2;
} else {
escapeChar = 'u';
length = 4;
}
return '\\' + escapeChar + javascript.padLeft(charCode.toString(16).toUpperCase(), '0', length);
},
/*
* Surrounds the string with quotes and escapes characters inside so that the
* result is a valid JavaScript string.
*
* The code needs to be in sync with the code template in the compilation
* function for "action" nodes.
*/
quote: function(s) {
/* /*
* ECMA-262, 5th ed., 7.8.4: All characters may appear literally in a string * ECMA-262, 5th ed., 7.8.4: All characters may appear literally in a string
* literal except for the closing quote character, backslash, carriage * literal except for the closing quote character, backslash, carriage
@ -58,23 +13,21 @@ var javascript = {
* Note that "\0" and "\v" escape sequences are not used because JSHint does * Note that "\0" and "\v" escape sequences are not used because JSHint does
* not like the first and IE the second. * not like the first and IE the second.
*/ */
return '"' + s return s
.replace(/\\/g, '\\\\') // backslash .replace(/\\/g, '\\\\') // backslash
.replace(/"/g, '\\"') // closing quote character .replace(/"/g, '\\"') // closing double quote
.replace(/\x08/g, '\\b') // backspace .replace(/\x08/g, '\\b') // backspace
.replace(/\t/g, '\\t') // horizontal tab .replace(/\t/g, '\\t') // horizontal tab
.replace(/\n/g, '\\n') // line feed .replace(/\n/g, '\\n') // line feed
.replace(/\f/g, '\\f') // form feed .replace(/\f/g, '\\f') // form feed
.replace(/\r/g, '\\r') // carriage return .replace(/\r/g, '\\r') // carriage return
.replace(/[\x00-\x07\x0B\x0E-\x1F\x80-\uFFFF]/g, javascript.escape) .replace(/[\x00-\x07\x0B\x0E\x0F]/g, function(ch) { return '\\x0' + hex(ch); })
+ '"'; .replace(/[\x10-\x1F\x80-\xFF]/g, function(ch) { return '\\x' + hex(ch); })
.replace(/[\u0180-\u0FFF]/g, function(ch) { return '\\u0' + hex(ch); })
.replace(/[\u1080-\uFFFF]/g, function(ch) { return '\\u' + hex(ch); });
}, },
/* regexpClassEscape: function(s) {
* Escapes characters inside the string so that it can be used as a list of
* characters in a character class of a regular expression.
*/
quoteForRegexpClass: function(s) {
/* /*
* Based on ECMA-262, 5th ed., 7.8.5 & 15.10.1. * Based on ECMA-262, 5th ed., 7.8.5 & 15.10.1.
* *
@ -92,7 +45,10 @@ var javascript = {
.replace(/\v/g, '\\x0B') // vertical tab .replace(/\v/g, '\\x0B') // vertical tab
.replace(/\f/g, '\\f') // form feed .replace(/\f/g, '\\f') // form feed
.replace(/\r/g, '\\r') // carriage return .replace(/\r/g, '\\r') // carriage return
.replace(/[\x01-\x08\x0E-\x1F\x80-\uFFFF]/g, javascript.escape); .replace(/[\x00-\x08\x0E\x0F]/g, function(ch) { return '\\x0' + hex(ch); })
.replace(/[\x10-\x1F\x80-\xFF]/g, function(ch) { return '\\x' + hex(ch); })
.replace(/[\u0100-\u0FFF]/g, function(ch) { return '\\u0' + hex(ch); })
.replace(/[\u1000-\uFFFF]/g, function(ch) { return '\\u' + hex(ch); });
} }
}; };

@ -285,7 +285,7 @@ function generateBytecode(ast) {
named: function(node, context) { named: function(node, context) {
var nameIndex = addConst( var nameIndex = addConst(
'{ type: "other", description: ' + js.quote(node.name) + ' }' '{ type: "other", description: "' + js.stringEscape(node.name) + '" }'
); );
/* /*
@ -516,15 +516,19 @@ function generateBytecode(ast) {
var stringIndex, expectedIndex; var stringIndex, expectedIndex;
if (node.value.length > 0) { if (node.value.length > 0) {
stringIndex = addConst(node.ignoreCase stringIndex = addConst('"'
? js.quote(node.value.toLowerCase()) + js.stringEscape(
: js.quote(node.value) node.ignoreCase ? node.value.toLowerCase() : node.value
)
+ '"'
); );
expectedIndex = addConst([ expectedIndex = addConst([
'{', '{',
'type: "literal",', 'type: "literal",',
'value: ' + js.quote(node.value) + ',', 'value: "' + js.stringEscape(node.value) + '",',
'description: ' + js.quote(js.quote(node.value)), 'description: "'
+ js.stringEscape('"' + js.stringEscape(node.value) + '"')
+ '"',
'}' '}'
].join(' ')); ].join(' '));
@ -557,10 +561,10 @@ function generateBytecode(ast) {
+ (node.inverted ? '^' : '') + (node.inverted ? '^' : '')
+ arrays.map(node.parts, function(part) { + arrays.map(node.parts, function(part) {
return part instanceof Array return part instanceof Array
? js.quoteForRegexpClass(part[0]) ? js.regexpClassEscape(part[0])
+ '-' + '-'
+ js.quoteForRegexpClass(part[1]) + js.regexpClassEscape(part[1])
: js.quoteForRegexpClass(part); : js.regexpClassEscape(part);
}).join('') }).join('')
+ ']/' + (node.ignoreCase ? 'i' : ''); + ']/' + (node.ignoreCase ? 'i' : '');
} else { } else {
@ -575,8 +579,8 @@ function generateBytecode(ast) {
expectedIndex = addConst([ expectedIndex = addConst([
'{', '{',
'type: "class",', 'type: "class",',
'value: ' + js.quote(node.rawText) + ',', 'value: "' + js.stringEscape(node.rawText) + '",',
'description: ' + js.quote(node.rawText), 'description: "' + js.stringEscape(node.rawText) + '"',
'}' '}'
].join(' ')); ].join(' '));

@ -22,12 +22,12 @@ function generateJavaScript(ast, options) {
indent2(arrays.map( indent2(arrays.map(
ast.rules, ast.rules,
function(rule) { function(rule) {
return 'peg$decode(' return 'peg$decode("'
+ js.quote(arrays.map( + js.stringEscape(arrays.map(
rule.bytecode, rule.bytecode,
function(b) { return String.fromCharCode(b + 32); } function(b) { return String.fromCharCode(b + 32); }
).join('')) ).join(''))
+ ')'; + '")';
} }
).join(',\n')), ).join(',\n')),
'],' '],'

Loading…
Cancel
Save