aboutsummaryrefslogtreecommitdiff
path: root/lib/parse.js
diff options
context:
space:
mode:
Diffstat (limited to 'lib/parse.js')
-rw-r--r--lib/parse.js95
1 files changed, 54 insertions, 41 deletions
diff --git a/lib/parse.js b/lib/parse.js
index 5b77d675..bc72550f 100644
--- a/lib/parse.js
+++ b/lib/parse.js
@@ -145,6 +145,43 @@ function is_identifier_string(str) {
return /^[a-z_$][a-z0-9_$]*$/i.test(str);
}
+function decode_escape_sequence(seq) {
+ switch (seq[0]) {
+ case "b": return "\b";
+ case "f": return "\f";
+ case "n": return "\n";
+ case "r": return "\r";
+ case "t": return "\t";
+ case "u":
+ var code;
+ if (seq.length == 5) {
+ code = seq.slice(1);
+ } else if (seq[1] == "{" && seq.slice(-1) == "}") {
+ code = seq.slice(2, -1);
+ } else {
+ return;
+ }
+ var num = parseInt(code, 16);
+ if (num < 0 || isNaN(num)) return;
+ if (num < 0x10000) return String.fromCharCode(num);
+ if (num > 0x10ffff) return;
+ return String.fromCharCode((num >> 10) + 0xd7c0) + String.fromCharCode((num & 0x03ff) + 0xdc00);
+ case "v": return "\u000b";
+ case "x":
+ if (seq.length != 3) return;
+ var num = parseInt(seq.slice(1), 16);
+ if (num < 0 || isNaN(num)) return;
+ return String.fromCharCode(num);
+ case "\r":
+ case "\n":
+ return "";
+ default:
+ if (seq == "0") return "\0";
+ if (seq[0] >= "0" && seq[0] <= "9") return;
+ return seq;
+ }
+}
+
function parse_js_number(num) {
var match;
if (match = RE_BIN_NUMBER.exec(num)) return parseInt(match[1], 2);
@@ -340,36 +377,23 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
}
function read_escaped_char(in_string) {
- var ch = next(true, in_string);
- switch (ch.charCodeAt(0)) {
- case 110: return "\n";
- case 114: return "\r";
- case 116: return "\t";
- case 98: return "\b";
- case 118: return "\u000b"; // \v
- case 102: return "\f";
- case 120: return String.fromCharCode(hex_bytes(2)); // \x
- case 117: // \u
- if (peek() != "{") return String.fromCharCode(hex_bytes(4));
- next();
- var num = 0;
- do {
- var digit = parseInt(next(true), 16);
- if (isNaN(digit)) parse_error("Invalid hex-character pattern in string");
- num = num * 16 + digit;
- } while (peek() != "}");
- next();
- if (num < 0x10000) return String.fromCharCode(num);
- if (num > 0x10ffff) parse_error("Invalid character code: " + num);
- return String.fromCharCode((num >> 10) + 0xd7c0) + String.fromCharCode((num & 0x03ff) + 0xdc00);
- case 13: // \r
- // DOS newline
- if (peek() == "\n") next(true, in_string);
- case 10: return ""; // \n
- }
- if (ch >= "0" && ch <= "7")
- return read_octal_escape_sequence(ch);
- return ch;
+ var seq = next(true, in_string);
+ if (seq >= "0" && seq <= "7") return read_octal_escape_sequence(seq);
+ if (seq == "u") {
+ var ch = next(true, in_string);
+ seq += ch;
+ if (ch != "{") {
+ seq += next(true, in_string) + next(true, in_string) + next(true, in_string);
+ } else do {
+ ch = next(true, in_string);
+ seq += ch;
+ } while (ch != "}");
+ } else if (seq == "x") {
+ seq += next(true, in_string) + next(true, in_string);
+ }
+ var str = decode_escape_sequence(seq);
+ if (typeof str != "string") parse_error("Invalid escape sequence: \\" + seq);
+ return str;
}
function read_octal_escape_sequence(ch) {
@@ -388,17 +412,6 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
return String.fromCharCode(parseInt(ch, 8));
}
- function hex_bytes(n) {
- var num = 0;
- for (; n > 0; --n) {
- var digit = parseInt(next(true), 16);
- if (isNaN(digit))
- parse_error("Invalid hex-character pattern in string");
- num = (num << 4) | digit;
- }
- return num;
- }
-
var read_string = with_eof_error("Unterminated string constant", function(quote_char) {
var quote = next(), ret = "";
for (;;) {