Bug 917436 - Part 2: Use IDStart and IDContinue Unicode properties for identifiers. r=arai
authorAndré Bargull <andre.bargull@gmail.com>
Mon, 07 Nov 2016 16:14:35 +0100
changeset 321599 483dc75949fa
parent 321598 816fef70c11d
child 321600 788b95bf4ea3
push id30931
push userkwierso@gmail.com
push dateTue, 08 Nov 2016 21:58:36 +0000
treeherdermozilla-central@783356f1476e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersarai
bugs917436
milestone52.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 917436 - Part 2: Use IDStart and IDContinue Unicode properties for identifiers. r=arai
js/src/frontend/TokenStream.cpp
js/src/tests/ecma_6/Syntax/identifier_vertical_tilde.js
js/src/tests/ecma_6/Syntax/identifiers-with-extended-unicode-escape.js
js/src/tests/ecma_6/Syntax/unicode_other_id_continue.js
js/src/tests/ecma_6/Syntax/unicode_other_id_start.js
js/src/vm/Unicode.cpp
js/src/vm/Unicode.h
js/src/vm/make_unicode.py
--- a/js/src/frontend/TokenStream.cpp
+++ b/js/src/frontend/TokenStream.cpp
@@ -1158,22 +1158,22 @@ TokenStream::getTokenInternal(TokenKind*
             }
 
             goto retry;
         }
 
         tp = newToken(-1);
 
         static_assert('$' < 128,
-                      "IdentifierStart contains '$', but as !IsLetter('$'), "
+                      "IdentifierStart contains '$', but as !IsUnicodeIDStart('$'), "
                       "ensure that '$' is never handled here");
         static_assert('_' < 128,
-                      "IdentifierStart contains '_', but as !IsLetter('_'), "
+                      "IdentifierStart contains '_', but as !IsUnicodeIDStart('_'), "
                       "ensure that '_' is never handled here");
-        if (unicode::IsLetter(c)) {
+        if (unicode::IsUnicodeIDStart(c)) {
             identStart = userbuf.addressOfNextRawChar() - 1;
             hadUnicodeEscape = false;
             goto identifier;
         }
 
         goto badchar;
     }
 
new file mode 100644
--- /dev/null
+++ b/js/src/tests/ecma_6/Syntax/identifier_vertical_tilde.js
@@ -0,0 +1,20 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// U+2E2F (VERTICAL TILDE) is in Gc=Lm, but also in [:Pattern_Syntax:].
+// http://www.unicode.org/reports/tr31/
+const verticalTilde = 0x2E2F;
+
+// Leading character in identifier.
+assertThrowsInstanceOf(() => eval(`${String.fromCodePoint(verticalTilde)}`), SyntaxError);
+assertThrowsInstanceOf(() => eval(`\\u${verticalTilde.toString(16).padStart(4, "0")}`), SyntaxError);
+assertThrowsInstanceOf(() => eval(`\\u{${verticalTilde.toString(16)}}`), SyntaxError);
+
+// Not leading character in identifier.
+assertThrowsInstanceOf(() => eval(`A${String.fromCodePoint(verticalTilde)}`), SyntaxError);
+assertThrowsInstanceOf(() => eval(`A\\u${verticalTilde.toString(16).padStart(4, "0")}`), SyntaxError);
+assertThrowsInstanceOf(() => eval(`A\\u{${verticalTilde.toString(16)}}`), SyntaxError);
+
+if (typeof reportCompare === "function")
+    reportCompare(0, 0, "ok");
--- a/js/src/tests/ecma_6/Syntax/identifiers-with-extended-unicode-escape.js
+++ b/js/src/tests/ecma_6/Syntax/identifiers-with-extended-unicode-escape.js
@@ -100,50 +100,50 @@ const otherIdContinue = [
     0x136D,     // ETHIOPIC DIGIT FIVE, Gc=No
     0x136E,     // ETHIOPIC DIGIT SIX, Gc=No
     0x136F,     // ETHIOPIC DIGIT SEVEN, Gc=No
     0x1370,     // ETHIOPIC DIGIT EIGHT, Gc=No
     0x1371,     // ETHIOPIC DIGIT NINE, Gc=No
     0x19DA,     // NEW TAI LUE THAM DIGIT ONE, Gc=No
 ];
 
-for (let ident of [...idStart, ...otherIdStart_Unicode9]) {
+for (let ident of [...idStart, ...otherIdStart, ...otherIdStart_Unicode9]) {
     for (let count of leadingZeros) {
         let zeros = "0".repeat(count);
         eval(`
             let \\u{${zeros}${ident.toString(16)}} = 123;
             assertEq(${String.fromCodePoint(ident)}, 123);
         `);
     }
 }
 
-// Move this to the loop above when Bug 917436 is fixed.
-for (let ident of [...idStartSupplemental, ...otherIdStart]) {
+// Move this to the loop above when Bug 1197230 is fixed.
+for (let ident of [...idStartSupplemental]) {
     for (let zeros of leadingZeros) {
         assertThrowsInstanceOf(() => eval(`\\u{${zeros}${ident.toString(16)}}`), SyntaxError);
     }
 }
 
 for (let ident of [...idContinue, ...idContinueSupplemental, ...otherIdContinue]) {
     for (let zeros of leadingZeros) {
         assertThrowsInstanceOf(() => eval(`\\u{${zeros}${ident.toString(16)}}`), SyntaxError);
     }
 }
 
-for (let ident of [...idStart, ...otherIdStart_Unicode9, ...idContinue]) {
+for (let ident of [...idStart, ...otherIdStart, ...otherIdStart_Unicode9, ...idContinue, ...otherIdContinue]) {
     for (let zeros of leadingZeros) {
         eval(`
             let A\\u{${zeros}${ident.toString(16)}} = 123;
             assertEq(${String.fromCodePoint(0x41, ident)}, 123);
         `);
     }
 }
 
-// Move this to the loop above when Bug 917436 is fixed.
-for (let ident of [...idStartSupplemental, ...otherIdStart, ...idContinueSupplemental, ...otherIdContinue]) {
+// Move this to the loop above when Bug 1197230 is fixed.
+for (let ident of [...idStartSupplemental, ...idContinueSupplemental]) {
     for (let zeros of leadingZeros) {
         assertThrowsInstanceOf(() => eval(`\\u{${zeros}${ident.toString(16)}}`), SyntaxError);
     }
 }
 
 
 const notIdentifiers = [
     0x0000,     // NULL, Gc=Cc
new file mode 100644
--- /dev/null
+++ b/js/src/tests/ecma_6/Syntax/unicode_other_id_continue.js
@@ -0,0 +1,45 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// From PropList.txt (Unicode 9):
+const otherIdContinue = [
+    0x00B7,     // MIDDLE DOT, Gc=Po
+    0x0387,     // GREEK ANO TELEIA, Gc=Po
+    0x1369,     // ETHIOPIC DIGIT ONE, Gc=No
+    0x136A,     // ETHIOPIC DIGIT TWO, Gc=No
+    0x136B,     // ETHIOPIC DIGIT THREE, Gc=No
+    0x136C,     // ETHIOPIC DIGIT FOUR, Gc=No
+    0x136D,     // ETHIOPIC DIGIT FIVE, Gc=No
+    0x136E,     // ETHIOPIC DIGIT SIX, Gc=No
+    0x136F,     // ETHIOPIC DIGIT SEVEN, Gc=No
+    0x1370,     // ETHIOPIC DIGIT EIGHT, Gc=No
+    0x1371,     // ETHIOPIC DIGIT NINE, Gc=No
+    0x19DA,     // NEW TAI LUE THAM DIGIT ONE, Gc=No
+];
+
+// Leading character in identifier.
+for (let ident of [...otherIdContinue]) {
+    assertThrowsInstanceOf(() => eval(`${String.fromCodePoint(ident)}`), SyntaxError);
+    assertThrowsInstanceOf(() => eval(`\\u${ident.toString(16).padStart(4, "0")}`), SyntaxError);
+    assertThrowsInstanceOf(() => eval(`\\u{${ident.toString(16)}}`), SyntaxError);
+}
+
+// Not leading character in identifier.
+for (let ident of [...otherIdContinue]) {
+    eval(`
+        let A${String.fromCodePoint(ident)} = 123;
+        assertEq(${String.fromCodePoint(0x41, ident)}, 123);
+    `);
+    eval(`
+        let A\\u${ident.toString(16).padStart(4, "0")} = 123;
+        assertEq(${String.fromCodePoint(0x41, ident)}, 123);
+    `);
+    eval(`
+        let A\\u{${ident.toString(16)}} = 123;
+        assertEq(${String.fromCodePoint(0x41, ident)}, 123);
+    `);
+}
+
+if (typeof reportCompare === "function")
+    reportCompare(0, 0, "ok");
new file mode 100644
--- /dev/null
+++ b/js/src/tests/ecma_6/Syntax/unicode_other_id_start.js
@@ -0,0 +1,55 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// From PropList.txt (Unicode 9):
+const otherIdStart = [
+    // Enable the following lines when Bug 1282724 is fixed.
+    // 0x1885,     // MONGOLIAN LETTER ALI GALI BALUDA, Gc=Mn
+    // 0x1886,     // MONGOLIAN LETTER ALI GALI THREE BALUDA, Gc=Mn
+    0x2118,     // SCRIPT CAPITAL P, Gc=Sm
+    0x212E,     // ESTIMATED SYMBOL, Gc=So
+    0x309B,     // KATAKANA-HIRAGANA VOICED SOUND MARK, Gc=Sk
+    0x309C,     // KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK, Gc=Sk
+];
+
+// Remove this list when we support Unicode 9 (Bug 1282724).
+const otherIdStart_Unicode9 = [
+    0x1885,     // MONGOLIAN LETTER ALI GALI BALUDA, Gc=Mn
+    0x1886,     // MONGOLIAN LETTER ALI GALI THREE BALUDA, Gc=Mn
+];
+
+// Leading character in identifier.
+for (let ident of [...otherIdStart, ...otherIdStart_Unicode9]) {
+    eval(`
+        let ${String.fromCodePoint(ident)} = 123;
+        assertEq(${String.fromCodePoint(ident)}, 123);
+    `);
+    eval(`
+        let \\u${ident.toString(16).padStart(4, "0")} = 123;
+        assertEq(${String.fromCodePoint(ident)}, 123);
+    `);
+    eval(`
+        let \\u{${ident.toString(16)}} = 123;
+        assertEq(${String.fromCodePoint(ident)}, 123);
+    `);
+}
+
+// Not leading character in identifier.
+for (let ident of [...otherIdStart, ...otherIdStart_Unicode9]) {
+    eval(`
+        let A${String.fromCodePoint(ident)} = 123;
+        assertEq(${String.fromCodePoint(0x41, ident)}, 123);
+    `);
+    eval(`
+        let A\\u${ident.toString(16).padStart(4, "0")} = 123;
+        assertEq(${String.fromCodePoint(0x41, ident)}, 123);
+    `);
+    eval(`
+        let A\\u{${ident.toString(16)}} = 123;
+        assertEq(${String.fromCodePoint(0x41, ident)}, 123);
+    `);
+}
+
+if (typeof reportCompare === "function")
+    reportCompare(0, 0, "ok");
--- a/js/src/vm/Unicode.cpp
+++ b/js/src/vm/Unicode.cpp
@@ -204,43 +204,43 @@ const uint8_t unicode::index1[] = {
       0,   1,   2,   3,   4,   5,   6,   7,   8,   9,  10,  11,  12,  13,  14,  15,   8,  16,
      17,  18,  19,  20,  21,  22,  23,  23,  24,  25,  26,  27,  28,  29,  30,  31,  32,   8,
      33,   8,  34,   8,   8,  35,  36,  37,  38,  39,  40,  41,  42,  20,  43,  44,  20,  20,
      45,  46,  47,  48,  49,  20,  20,  50,  51,  52,  53,  54,  55,   4,   4,  56,   4,  57,
      58,  59,  60,  61,  62,  63,  64,  65,  66,  67,  68,  69,  70,  71,  72,  73,  62,  71,
      74,  75,  76,  77,  78,  79,  80,  81,  82,  73,  83,  84,  85,  86,  83,  87,  88,  89,
      90,  91,  92,  93,  94,  95,  96,   4,  97,  98,  99,   4, 100, 101, 102, 103, 104, 105,
     106,   4,  20, 107, 108, 109, 110, 111, 112, 113,  20,  20,  20,  20,  20,  20,  20,  20,
-     20,  20, 114,  20, 115, 116, 117,  20, 118,  20, 119,   4, 120,  20,  20, 121,  94,  20,
-     20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20, 122,
-    123,  20,  20, 124, 125, 126, 127, 128,  20, 129, 130, 131, 132,  20,  20, 133,  20, 134,
-     20, 135, 136, 137, 138, 139,  20, 140, 141,   4, 142,  20, 143, 144, 145, 146,   4,   4,
-    147, 129, 148, 149, 150, 151,  20, 152,  20, 153, 154, 155,   4,   4, 156, 157,  20,  20,
-     20, 158,  20,  20,  23, 159,   8,   8,   8,   8, 160,   8,   8,   8, 161, 162, 163, 164,
-    162, 165, 166, 167, 168, 169, 170, 171, 172,   4, 173, 174, 175, 176, 177, 178, 179,   4,
+     20,  20, 114,  20, 115, 116, 117,  20, 118,  20, 119, 120, 121,  20,  20, 122,  94,  20,
+     20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20, 123,
+    124,  20,  20, 125, 126, 127, 128, 129,  20, 130, 131, 132, 133,  20,  20, 134,  20, 135,
+     20, 136, 137, 138, 139, 140,  20, 141, 142,   4, 143,  20, 144, 145, 146, 147,   4,   4,
+    148, 130, 149, 150, 151, 152,  20, 153,  20, 154, 155, 156,   4,   4, 157, 158,  20,  20,
+     20, 159,  20,  20,  23, 160,   8,   8,   8,   8, 161,   8,   8,   8, 162, 163, 164, 165,
+    163, 166, 167, 168, 169, 170, 171, 172, 173,   4, 174, 175, 176, 177, 178, 179, 180,   4,
       4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
-      4,   4,   4,   4,   4, 180, 181, 182,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
+      4,   4,   4,   4,   4, 181, 182, 183,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
       4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
       4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
-      4,   4,   4,   4,   4,   4,   4,   4,   4,   4, 183, 184, 185, 186,   8,   8,   8, 187,
-    188, 189,  20, 190, 191, 192, 192,  23,   4, 193,   4,   4,   4,   4,   4,   4,   4,   4,
+      4,   4,   4,   4,   4,   4,   4,   4,   4,   4, 184, 185, 186, 187,   8,   8,   8, 188,
+    189, 190,  20, 191, 192, 193, 193,  23,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
       4,   4,   4,   4,   4,   4, 194, 195,  94,  20, 196,  94,  20, 113, 197, 198,  20,  20,
     199, 200,   4, 201,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
       4,   4,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,
      20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,
      20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,
      20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,
      20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,
      20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,
      20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,
      20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,
      20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,
      20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,
      20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,
-     20,  20,  20,  20,  20,  20,  20,  20,  20, 135,   4,   4,  20,  20,  20,  20,  20,  20,
+     20,  20,  20,  20,  20,  20,  20,  20,  20, 136,   4,   4,  20,  20,  20,  20,  20,  20,
      20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,
      20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,
      20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,
      20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,
      20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,
      20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,
      20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,
      20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,
@@ -269,19 +269,19 @@ const uint8_t unicode::index1[] = {
      20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,
      20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,
      20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,
      20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,
      20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,
      20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,
     202,   4,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,
      20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,
-     20,  20, 202,   4, 201, 155,  20,  20,  20,  20,  20,  20,  20,  20, 203, 204,   8, 205,
-    206,  20,  20, 207, 208, 209,   8, 210, 211, 212,   4, 213, 214, 215,  20, 216, 217, 129,
-    218, 219,  51, 220, 221, 136,  58, 222, 223,   4,  20, 224, 225, 226,  20, 227, 228, 229,
+     20,  20, 202,   4, 201, 156,  20,  20,  20,  20,  20,  20,  20,  20, 203, 204,   8, 205,
+    206,  20,  20, 207, 208, 209,   8, 210, 211, 212,   4, 213, 214, 215,  20, 216, 217, 130,
+    218, 219,  51, 220, 221, 137,  58, 222, 223,   4,  20, 224, 225, 226,  20, 227, 228, 229,
     230, 231,   4,   4,   4,   4,  20, 232,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,
      20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,
      20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,
      20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,
      20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,
      20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,
      20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,
      20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,
@@ -308,32 +308,32 @@ const uint8_t unicode::index1[] = {
       4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
       4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
       4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
       4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
       4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
       4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
       4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,  20,  20,  20,  20,  20,  20,
      20,  20,  20,  20,  20, 236,  20,  20, 237,   4, 238, 239, 240,  20,  20, 241, 242,  20,
-     20,  20,  20,  20,  20,  20,  20,  20,  20, 155, 201,  20, 243,  20, 244, 245, 246, 247,
+     20,  20,  20,  20,  20,  20,  20,  20,  20, 156, 201,  20, 243,  20, 244, 245, 246, 247,
     248, 249,  20,  20,  20, 250, 251,   2,   3, 252,  20, 253, 254,   4,
 };
 
 const uint8_t unicode::index2[] = {
       0,   0,   0,   0,   0,   0,   0,   0,   0,   1,   1,   1,   1,   1,   0,   0,   0,   0,
       0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   1,   0,   0,   0,
       0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   2,   2,   2,   2,   2,   2,
       2,   2,   2,   2,   0,   0,   0,   0,   0,   0,   0,   3,   3,   3,   3,   3,   3,   3,
       3,   3,   3,   3,   3,   3,   3,   3,   3,   3,   3,   3,   3,   3,   3,   3,   3,   3,
       3,   0,   0,   0,   0,   2,   0,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
       4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   0,   0,   0,
       0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
       0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   1,   0,
       0,   0,   0,   0,   0,   0,   0,   0,   5,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-      0,   6,   0,   0,   0,   0,   5,   0,   0,   0,   0,   0,   3,   3,   3,   3,   3,   3,
+      0,   6,   0,   2,   0,   0,   5,   0,   0,   0,   0,   0,   3,   3,   3,   3,   3,   3,
       3,   3,   3,   3,   3,   3,   3,   3,   3,   3,   3,   3,   3,   3,   3,   3,   3,   0,
       3,   3,   3,   3,   3,   3,   3,   5,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
       4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   0,   4,   4,   4,   4,
       4,   4,   4,   7,   8,   9,   8,   9,   8,   9,   8,   9,   8,   9,   8,   9,   8,   9,
       8,   9,   8,   9,   8,   9,   8,   9,   8,   9,   8,   9,   8,   9,   8,   9,   8,   9,
       8,   9,   8,   9,   8,   9,   8,   9,   8,   9,   8,   9,   8,   9,   8,   9,  10,  11,
       8,   9,   8,   9,   8,   9,   5,   8,   9,   8,   9,   8,   9,   8,   9,   8,   9,   8,
       9,   8,   9,   8,   9,   5,   8,   9,   8,   9,   8,   9,   8,   9,   8,   9,   8,   9,
@@ -359,17 +359,17 @@ const uint8_t unicode::index2[] = {
       5,   5,   5,   5,   5,   5,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
       0,   0,   5,   5,   5,   5,   5,   0,   0,   0,   0,   0,   0,   0,   5,   0,   5,   0,
       0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   2,   2,
       2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,
       2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,  70,
       2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,
       2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,
       2,   2,   2,   2,   2,   2,   8,   9,   8,   9,   5,   0,   8,   9,   0,   0,   5,  27,
-     27,  27,   0,   0,   0,   0,   0,   0,   0,   0,  71,   0,  72,  72,  72,   0,  73,   0,
+     27,  27,   0,   0,   0,   0,   0,   0,   0,   0,  71,   2,  72,  72,  72,   0,  73,   0,
      74,  74,   5,   3,   3,   3,   3,   3,   3,   3,   3,   3,   3,   3,   3,   3,   3,   3,
       3,   3,   0,   3,   3,   3,   3,   3,   3,   3,   3,   3,  75,  76,  76,  76,   5,   4,
       4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,  77,   4,
       4,   4,   4,   4,   4,   4,   4,   4,  78,  79,  79,  80,  81,  82,   5,   5,   5,  83,
      84,  85,   8,   9,   8,   9,   8,   9,   8,   9,   8,   9,   8,   9,   8,   9,   8,   9,
       8,   9,   8,   9,   8,   9,   8,   9,  86,  87,  88,   5,  89,  90,   0,   8,   9,  91,
       8,   9,   5,  39,  39,  39,  92,  92,  92,  92,  92,  92,  92,  92,  92,  92,  92,  92,
      92,  92,  92,  92,   3,   3,   3,   3,   3,   3,   3,   3,   3,   3,   3,   3,   3,   3,
@@ -526,154 +526,154 @@ const uint8_t unicode::index2[] = {
       5,   5,   5,   5,   0,   0,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,
       5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,
       5,   5,   5,   0,   5,   5,   5,   5,   0,   0,   5,   5,   5,   5,   5,   5,   5,   0,
       5,   0,   5,   5,   5,   5,   0,   0,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,
       5,   5,   5,   5,   5,   0,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,
       5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   0,   5,   5,   5,   5,
       0,   0,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,
       5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,
-      5,   0,   0,   2,   2,   2,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,
-      5,   5,   5,   5,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+      5,   0,   0,   2,   2,   2,   0,   0,   0,   0,   0,   0,   0,   0,   0,   2,   2,   2,
+      2,   2,   2,   2,   2,   2,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
       0,   0,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,
-      5,   5,   5,   5,   5,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   5,   5,
-      5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   0,   0,   5,   5,   5,   5,   5,
-      5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   1,   5,   5,   5,   5,   5,
+      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   5,   5,
       5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,
-      5,   5,   5,   0,   0,   0,   0,   0,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,
-      5,   0,   0,   0,   5,   5,   5,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-      0,   0,   0,   0,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   0,
-      5,   5,   5,   5,   2,   2,   2,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-      5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,
+      5,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   5,   5,   5,   5,   5,   5,
+      5,   5,   5,   5,   5,   5,   5,   0,   0,   5,   5,   5,   5,   5,   5,   5,   5,   5,
+      5,   5,   5,   5,   5,   5,   5,   5,   1,   5,   5,   5,   5,   5,   5,   5,   5,   5,
+      5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   0,
+      0,   0,   0,   0,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   0,   0,   0,
+      5,   5,   5,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+      5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   0,   5,   5,   5,   5,
       2,   2,   2,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   5,   5,   5,   5,
-      5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   2,   2,   0,   0,
+      5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   2,   2,   2,   0,
       0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   5,   5,   5,   5,   5,   5,   5,   5,
-      5,   5,   5,   5,   5,   0,   5,   5,   5,   0,   2,   2,   0,   0,   0,   0,   0,   0,
+      5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   2,   2,   0,   0,   0,   0,   0,   0,
       0,   0,   0,   0,   0,   0,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,
-      5,   5,   5,   5,   5,   5,   5,   5,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,
+      5,   0,   5,   5,   5,   0,   2,   2,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+      0,   0,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,
+      5,   5,   5,   5,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,
       2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,
-      2,   2,   2,   2,   0,   0,   0,   5,   0,   0,   0,   0,   5,   2,   0,   0,   2,   2,
-      2,   2,   2,   2,   2,   2,   2,   2,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+      0,   0,   0,   5,   0,   0,   0,   0,   5,   2,   0,   0,   2,   2,   2,   2,   2,   2,
+      2,   2,   2,   2,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
       0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-      0,   0,   0,   0,   0,   2,   2,   2,   1,   0,   2,   2,   2,   2,   2,   2,   2,   2,
-      2,   2,   0,   0,   0,   0,   0,   0,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,
-      5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   0,   0,   0,   0,
-      0,   0,   0,   0,   5,   5,   5,   5,   5,   5,   5,   5,   5,   2,   5,   0,   0,   0,
-      0,   0,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,
+      0,   2,   2,   2,   1,   0,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   0,   0,
+      0,   0,   0,   0,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,
+      5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   0,   0,   0,   0,   0,   0,   0,   0,
+      5,   5,   5,   5,   5,   5,   5,   5,   5,   2,   5,   0,   0,   0,   0,   0,   5,   5,
       5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,
-      5,   5,   5,   5,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   5,   5,   5,   5,
+      5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,
+      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   5,   5,   5,   5,   5,   5,   5,   5,
       5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,
-      5,   5,   5,   5,   5,   5,   5,   0,   0,   0,   2,   2,   2,   2,   2,   2,   2,   2,
-      2,   2,   2,   2,   0,   0,   0,   0,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,
-      2,   2,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   2,   2,   2,   2,   2,   2,
-      2,   2,   2,   2,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,
-      5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   0,   0,
-      5,   5,   5,   5,   5,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   5,   5,
-      5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   0,   0,   0,   0,   2,   2,   2,   2,
-      2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   5,   5,   5,   5,   5,
-      5,   5,   2,   2,   0,   0,   0,   0,   0,   0,   2,   2,   2,   2,   2,   2,   2,   2,
-      2,   2,   0,   0,   0,   0,   0,   0,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,
-      5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   2,   2,   2,   2,   2,
+      5,   5,   5,   0,   0,   0,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,
+      0,   0,   0,   0,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   0,   0,
+      0,   0,   0,   0,   0,   0,   0,   0,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,
+      5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,
+      5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   0,   0,   5,   5,   5,   5,
+      5,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   5,   5,   5,   5,   5,   5,
+      5,   5,   5,   5,   5,   5,   0,   0,   0,   0,   2,   2,   2,   2,   2,   2,   2,   2,
+      2,   2,   2,   2,   2,   2,   2,   2,   2,   5,   5,   5,   5,   5,   5,   5,   2,   2,
+      0,   0,   0,   0,   0,   0,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   0,
       0,   0,   0,   0,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,
-      5,   5,   5,   5,   5,   5,   5,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   0,
-      2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,
-      2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   0,   0,   2,   2,   2,   2,   2,
-      2,   2,   2,   2,   2,   2,   0,   0,   0,   0,   0,   0,   2,   2,   2,   2,   2,   2,
-      2,   2,   2,   2,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   5,
-      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-      0,   0,   0,   0,   0,   0,   2,   2,   2,   2,   2,   5,   5,   5,   5,   5,   5,   5,
+      5,   5,   5,   5,   5,   5,   5,   5,   5,   2,   2,   2,   2,   2,   0,   0,   0,   0,
       5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,
-      5,   5,   2,   2,   2,   2,   2,   5,   5,   5,   5,   5,   5,   5,   0,   0,   0,   0,
-      2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   0,   0,   0,   0,   0,   0,   0,   0,
-      0,   0,   0,   0,   0,   0,   0,   0,   0,   2,   2,   2,   2,   2,   2,   2,   2,   2,
-      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   2,   2,   2,   5,   5,   5,
-      5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,
-      5,   5,   5,   5,   5,   5,   5,   5,   5,   2,   2,   2,   2,   2,   2,   2,   2,   2,
-      2,   2,   2,   2,   5,   5,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   5,   5,
-      5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   2,   2,   2,   2,   2,   2,   2,   2,
+      5,   5,   5,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   0,   2,   2,   2,   2,
+      2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,
+      2,   2,   2,   2,   2,   2,   2,   0,   0,   2,   2,   2,   2,   2,   2,   2,   2,   2,
+      2,   2,   0,   0,   0,   0,   0,   0,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,
+      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   5,   0,   0,   0,   0,
+      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+      0,   0,   2,   2,   2,   2,   2,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,
+      5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   2,   2,
+      2,   2,   2,   5,   5,   5,   5,   5,   5,   5,   0,   0,   0,   0,   2,   2,   2,   2,
       2,   2,   2,   2,   2,   2,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-      5,   5,   5,   5,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,
-      2,   2,   2,   2,   2,   2,   0,   0,   0,   0,   0,   0,   0,   0,   2,   2,   2,   2,
-      2,   2,   2,   2,   2,   2,   0,   0,   0,   5,   5,   5,   2,   2,   2,   2,   2,   2,
-      2,   2,   2,   2,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,
+      0,   0,   0,   0,   0,   2,   2,   2,   2,   2,   2,   2,   2,   2,   0,   0,   0,   0,
+      0,   0,   0,   0,   0,   0,   0,   0,   2,   2,   2,   5,   5,   5,   5,   5,   5,   5,
+      5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,
+      5,   5,   5,   5,   5,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,
+      5,   5,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   5,   5,   5,   5,   5,   5,
+      5,   5,   5,   5,   5,   5,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,
+      2,   2,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   5,   5,   5,   5,
+      2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,
+      2,   2,   0,   0,   0,   0,   0,   0,   0,   0,   2,   2,   2,   2,   2,   2,   2,   2,
+      2,   2,   0,   0,   0,   5,   5,   5,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,
       5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,
-      5,   5,   5,   5,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-      0,   0,   0,   0,   2,   2,   2,   0,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,
-      2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   5,   5,   5,   5,   2,   5,   5,
-      5,   5,   2,   2,   2,   5,   5,   0,   0,   0,   0,   0,   0,   0,   0,   0,   5,   5,
       5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,
-      5,   5,   5,   5,   5,  98,   5,   5,   5,  99,   5,   5,   2,   2,   2,   2,   2,   2,
-      2,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-      0,   0,   0,   0,   2,   2,   2,   2,   8,   9,   8,   9,   8,   9,   8,   9,   8,   9,
-      8,   9,   8,   9,   8,   9,   8,   9,   8,   9,   8,   9,   5,   5,   5,   5,   5, 100,
-      5,   5, 101,   5, 102, 102, 102, 102, 102, 102, 102, 102, 103, 103, 103, 103, 103, 103,
-    103, 103, 102, 102, 102, 102, 102, 102,   0,   0, 103, 103, 103, 103, 103, 103,   0,   0,
+      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+      2,   2,   2,   0,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,
+      2,   2,   2,   2,   2,   2,   2,   5,   5,   5,   5,   2,   5,   5,   5,   5,   2,   2,
+      2,   5,   5,   0,   0,   0,   0,   0,   0,   0,   0,   0,   5,   5,   5,   5,   5,   5,
+      5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,
+      5,  98,   5,   5,   5,  99,   5,   5,   2,   2,   2,   2,   2,   2,   2,   0,   0,   0,
+      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+      2,   2,   2,   2,   8,   9,   8,   9,   8,   9,   8,   9,   8,   9,   8,   9,   8,   9,
+      8,   9,   8,   9,   8,   9,   8,   9,   5,   5,   5,   5,   5, 100,   5,   5, 101,   5,
     102, 102, 102, 102, 102, 102, 102, 102, 103, 103, 103, 103, 103, 103, 103, 103, 102, 102,
-    102, 102, 102, 102, 102, 102, 103, 103, 103, 103, 103, 103, 103, 103, 102, 102, 102, 102,
-    102, 102,   0,   0, 103, 103, 103, 103, 103, 103,   0,   0,   5, 102,   5, 102,   5, 102,
-      5, 102,   0, 103,   0, 103,   0, 103,   0, 103, 102, 102, 102, 102, 102, 102, 102, 102,
-    103, 103, 103, 103, 103, 103, 103, 103, 104, 104, 105, 105, 105, 105, 106, 106, 107, 107,
-    108, 108, 109, 109,   0,   0, 102, 102, 102, 102, 102, 102, 102, 102, 103, 103, 103, 103,
-    103, 103, 103, 103, 102, 102,   5, 110,   5,   0,   5,   5, 103, 103, 111, 111, 112,   0,
-    113,   0,   0,   0,   5, 110,   5,   0,   5,   5, 114, 114, 114, 114, 112,   0,   0,   0,
-    102, 102,   5,   5,   0,   0,   5,   5, 103, 103, 115, 115,   0,   0,   0,   0, 102, 102,
-      5,   5,   5,  88,   5,   5, 103, 103, 116, 116,  91,   0,   0,   0,   0,   0,   5, 110,
-      5,   0,   5,   5, 117, 117, 118, 118, 112,   0,   0,   0,   1,   1,   1,   1,   1,   1,
-      1,   1,   1,   1,   1,   0,   2,   2,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   1,   1,
-      0,   0,   0,   0,   0,   1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-      0,   0,   0,   2,   2,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-      0,   0,   0,   0,   0,   0,   2,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   1,
-      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   5,
+    102, 102, 102, 102,   0,   0, 103, 103, 103, 103, 103, 103,   0,   0, 102, 102, 102, 102,
+    102, 102, 102, 102, 103, 103, 103, 103, 103, 103, 103, 103, 102, 102, 102, 102, 102, 102,
+    102, 102, 103, 103, 103, 103, 103, 103, 103, 103, 102, 102, 102, 102, 102, 102,   0,   0,
+    103, 103, 103, 103, 103, 103,   0,   0,   5, 102,   5, 102,   5, 102,   5, 102,   0, 103,
+      0, 103,   0, 103,   0, 103, 102, 102, 102, 102, 102, 102, 102, 102, 103, 103, 103, 103,
+    103, 103, 103, 103, 104, 104, 105, 105, 105, 105, 106, 106, 107, 107, 108, 108, 109, 109,
+      0,   0, 102, 102, 102, 102, 102, 102, 102, 102, 103, 103, 103, 103, 103, 103, 103, 103,
+    102, 102,   5, 110,   5,   0,   5,   5, 103, 103, 111, 111, 112,   0, 113,   0,   0,   0,
+      5, 110,   5,   0,   5,   5, 114, 114, 114, 114, 112,   0,   0,   0, 102, 102,   5,   5,
+      0,   0,   5,   5, 103, 103, 115, 115,   0,   0,   0,   0, 102, 102,   5,   5,   5,  88,
+      5,   5, 103, 103, 116, 116,  91,   0,   0,   0,   0,   0,   5, 110,   5,   0,   5,   5,
+    117, 117, 118, 118, 112,   0,   0,   0,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,
+      1,   0,   2,   2,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   1,   1,   0,   0,   0,   0,
+      0,   1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   2,
+      2,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+      0,   0,   2,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   1,   0,   0,   0,   0,
       0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   5,   0,   0,   0,   0,
-      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   5,   5,   5,   5,   5,   5,
-      5,   5,   5,   5,   5,   5,   5,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-      0,   0,   0,   0,   0,   0,   0,   0,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,
-      2,   2,   2,   0,   0,   0,   0,   2,   0,   0,   0,   2,   2,   2,   2,   2,   2,   2,
-      2,   2,   2,   2,   2,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-      0,   0,   0,   0,   5,   0,   0,   0,   0,   5,   0,   0,   5,   5,   5,   5,   5,   5,
-      5,   5,   5,   5,   0,   5,   0,   0,   0,   5,   5,   5,   5,   5,   0,   0,   0,   0,
-      0,   0,   5,   0, 119,   0,   5,   0, 120, 121,   5,   5,   0,   5,   5,   5, 122,   5,
-      5,   5,   5,   5,   5,   5,   0,   0,   5,   5,   5,   5,   0,   0,   0,   0,   0,   5,
-      5,   5,   5,   5,   0,   0,   0,   0, 123,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-      0,   0,   0,   0,   0,   0,   0,   0, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
-    124, 124, 124, 124, 124, 124, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
-    125, 125, 125, 125,   5,   5,   5,   8,   9,   5,   5,   5,   5,   0,   0,   0,   0,   0,
+      0,   0,   0,   0,   0,   0,   0,   0,   0,   5,   0,   0,   0,   0,   0,   0,   0,   0,
+      0,   0,   0,   0,   0,   0,   0,   0,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,
+      5,   5,   5,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+      0,   0,   0,   0,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   0,
+      0,   0,   0,   2,   0,   0,   0,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,
+      2,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+      5,   0,   0,   0,   0,   5,   0,   0,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,
+      0,   5,   0,   0,   5,   5,   5,   5,   5,   5,   0,   0,   0,   0,   0,   0,   5,   0,
+    119,   0,   5,   0, 120, 121,   5,   5,   5,   5,   5,   5, 122,   5,   5,   5,   5,   5,
+      5,   5,   0,   0,   5,   5,   5,   5,   0,   0,   0,   0,   0,   5,   5,   5,   5,   5,
+      0,   0,   0,   0, 123,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+      0,   0,   0,   0, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
+    124, 124, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
+      5,   5,   5,   8,   9,   5,   5,   5,   5,   0,   0,   0,   0,   0,   0,   0,   0,   0,
       0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
       0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-      0,   0,   0,   0, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126,
-    126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 127, 127, 127, 127, 127, 127,
-    127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
-    127, 127,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-      0,   0,   0,   0,   0,   0,  95,  95,  95,  95,  95,  95,  95,  95,  95,  95,  95,  95,
+    126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126,
+    126, 126, 126, 126, 126, 126, 126, 126, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
+    127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,   0,   0,
+      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+      0,   0,  95,  95,  95,  95,  95,  95,  95,  95,  95,  95,  95,  95,  95,  95,  95,  95,
      95,  95,  95,  95,  95,  95,  95,  95,  95,  95,  95,  95,  95,  95,  95,  95,  95,  95,
-     95,  95,  95,  95,  95,  95,  95,  95,  95,  95,  95,  95,  95,  95,  95,  95,  95,   0,
+     95,  95,  95,  95,  95,  95,  95,  95,  95,  95,  95,  95,  95,   0,  96,  96,  96,  96,
      96,  96,  96,  96,  96,  96,  96,  96,  96,  96,  96,  96,  96,  96,  96,  96,  96,  96,
      96,  96,  96,  96,  96,  96,  96,  96,  96,  96,  96,  96,  96,  96,  96,  96,  96,  96,
-     96,  96,  96,  96,  96,  96,  96,  96,  96,  96,  96,   0,   8,   9, 128, 129, 130, 131,
-    132,   8,   9,   8,   9,   8,   9, 133, 134, 135, 136,   5,   8,   9,   5,   8,   9,   5,
-      5,   5,   5,   5,   5,   5, 137, 137,   8,   9,   8,   9,   5,   0,   0,   0,   0,   0,
-      0,   8,   9,   8,   9,   2,   2,   2,   8,   9,   0,   0,   0,   0,   0,   0,   0,   0,
-      0,   0,   0,   0, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138,
+     96,  96,  96,  96,  96,  96,  96,   0,   8,   9, 128, 129, 130, 131, 132,   8,   9,   8,
+      9,   8,   9, 133, 134, 135, 136,   5,   8,   9,   5,   8,   9,   5,   5,   5,   5,   5,
+      5,   5, 137, 137,   8,   9,   8,   9,   5,   0,   0,   0,   0,   0,   0,   8,   9,   8,
+      9,   2,   2,   2,   8,   9,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
     138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138,
-    138, 138, 138, 138, 138, 138,   0, 138,   0,   0,   0,   0,   0, 138,   0,   0,   5,   5,
+    138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138,
+    138, 138,   0, 138,   0,   0,   0,   0,   0, 138,   0,   0,   5,   5,   5,   5,   5,   5,
       5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,
-      5,   5,   5,   5,   0,   0,   0,   0,   0,   0,   0,   5,   0,   0,   0,   0,   0,   0,
-      0,   0,   0,   0,   0,   0,   0,   0,   0,   2,   5,   5,   5,   5,   5,   5,   5,   5,
-      5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   0,   0,   0,
-      0,   0,   0,   0,   0,   0,   5,   5,   5,   5,   5,   5,   5,   0,   5,   5,   5,   5,
-      5,   5,   5,   0,   5,   5,   5,   5,   5,   5,   5,   0,   5,   5,   5,   5,   5,   5,
-      5,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   5,
-      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   1,   0,
+      0,   0,   0,   0,   0,   0,   0,   5,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+      0,   0,   0,   0,   0,   2,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,
+      5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   0,   0,   0,   0,   0,   0,   0,
+      0,   0,   5,   5,   5,   5,   5,   5,   5,   0,   5,   5,   5,   5,   5,   5,   5,   0,
+      5,   5,   5,   5,   5,   5,   5,   0,   5,   5,   5,   5,   5,   5,   5,   0,   1,   0,
       0,   0,   0,   5,   5,   5,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
       0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   5,   5,   5,   5,   5,
       5,   5,   5,   5,   2,   2,   2,   2,   2,   2,   0,   5,   5,   5,   5,   5,   0,   0,
       5,   5,   5,   5,   5,   0,   0,   0,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,
-      5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   0,   0,   2,   2,   0,
-      0,   5,   5,   5,   0,   0,   0,   0,   0,   5,   5,   5,   5,   5,   5,   5,   5,   5,
+      5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   0,   0,   2,   2,   5,
+      5,   5,   5,   5,   0,   0,   0,   0,   0,   5,   5,   5,   5,   5,   5,   5,   5,   5,
       5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,
       5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   0,   0,   0,   5,
       5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,
       5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   0,   0,   0,   0,   0,   0,   0,
       0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   5,   5,   5,   5,   5,   5,   5,   5,
       5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,
       5,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
       0,   0,   0,   0,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,   5,
--- a/js/src/vm/Unicode.h
+++ b/js/src/vm/Unicode.h
@@ -13,62 +13,60 @@
 extern const bool js_isidstart[];
 extern const bool js_isident[];
 extern const bool js_isspace[];
 
 namespace js {
 namespace unicode {
 
 /*
- * This enum contains the all the knowledge required to handle
- * Unicode in JavaScript.
+ * This namespace contains all the knowledge required to handle Unicode
+ * characters in JavaScript.
  *
  * SPACE
- *   Every character that is either in the ECMA-262 5th Edition
- *   class WhiteSpace or LineTerminator.
+ *   Every character that is either in the ECMAScript class WhiteSpace
+ *   (ES2016, § 11.2) or in LineTerminator (ES2016, § 11.3).
  *
  *   WhiteSpace
  *    \u0009, \u000B, \u000C, \u0020, \u00A0 and \uFEFF
  *    and every other Unicode character with the General Category "Zs".
- *    In pratice this is every character with the value "Zs" as the third
- *    field (after the char code in hex, and the name) called General_Category
- *    (see http://www.unicode.org/reports/tr44/#UnicodeData.txt)
- *     in the file UnicodeData.txt.
+ *    See <http://www.unicode.org/reports/tr44/#UnicodeData.txt> for more
+ *    information about General Categories and the UnicodeData.txt file.
  *
  *   LineTerminator
  *    \u000A, \u000D, \u2028, \u2029
  *
- * LETTER
- *   This are all characters included UnicodeLetter from ECMA-262.
- *   This includes the category 'Lu', 'Ll', 'Lt', 'Lm', 'Lo', 'Nl'
+ * UNICODE_ID_START
+ *   These are all characters with the Unicode property «ID_Start».
  *
- * IDENTIFIER_PART
- *   This is UnicodeCombiningMark, UnicodeDigit, UnicodeConnectorPunctuation.
- *   Aka categories Mn/Mc, Md, Nd, Pc
- *   And <ZWNJ> and <ZWJ>.
- *   Attention: FLAG_LETTER is _not_ IdentifierStart, but you could build
+ * UNICODE_ID_CONTINUE_ONLY
+ *   These are all characters with the Unicode property «ID_Continue» minus all
+ *   characters with the Unicode property «ID_Start».
+ *   And additionally <ZWNJ> and <ZWJ>. (ES2016, § 11.6)
+ *
+ * UNICODE_ID_CONTINUE
+ *   These are all characters with the Unicode property «ID_Continue».
+ *   And additionally <ZWNJ> and <ZWJ>. (ES2016, § 11.6)
+ *
+ *   Attention: UNICODE_ID_START is _not_ IdentifierStart, but you could build
  *   a matcher for the real IdentifierPart like this:
  *
- *   if isEscapeSequence():
- *      handleEscapeSequence()
- *      return True
  *   if char in ['$', '_']:
  *      return True
- *   if GetFlag(char) & (FLAG_IDENTIFIER_PART | FLAG_LETTER):
+ *   if GetFlag(char) & UNICODE_ID_CONTINUE:
  *      return True
  *
  */
 
-struct CharFlag {
-    enum temp {
-        SPACE  = 1 << 0,
-        LETTER = 1 << 1,
-        IDENTIFIER_PART = 1 << 2,
-    };
-};
+namespace CharFlag {
+    const uint8_t SPACE = 1 << 0;
+    const uint8_t UNICODE_ID_START = 1 << 1;
+    const uint8_t UNICODE_ID_CONTINUE_ONLY = 1 << 2;
+    const uint8_t UNICODE_ID_CONTINUE = UNICODE_ID_START + UNICODE_ID_CONTINUE_ONLY;
+}
 
 const char16_t BYTE_ORDER_MARK2 = 0xFFFE;
 const char16_t NO_BREAK_SPACE  = 0x00A0;
 
 const char16_t LeadSurrogateMin = 0xD800;
 const char16_t LeadSurrogateMax = 0xDBFF;
 const char16_t TrailSurrogateMin = 0xDC00;
 const char16_t TrailSurrogateMax = 0xDFFF;
@@ -98,22 +96,23 @@ class CharacterInfo {
     uint16_t upperCase;
     uint16_t lowerCase;
     uint8_t flags;
 
     inline bool isSpace() const {
         return flags & CharFlag::SPACE;
     }
 
-    inline bool isLetter() const {
-        return flags & CharFlag::LETTER;
+    inline bool isUnicodeIDStart() const {
+        return flags & CharFlag::UNICODE_ID_START;
     }
 
-    inline bool isIdentifierPart() const {
-        return flags & (CharFlag::IDENTIFIER_PART | CharFlag::LETTER);
+    inline bool isUnicodeIDContinue() const {
+        // Also matches <ZWNJ> and <ZWJ>!
+        return flags & CharFlag::UNICODE_ID_CONTINUE;
     }
 };
 
 extern const uint8_t index1[];
 extern const uint8_t index2[];
 extern const CharacterInfo js_charinfo[];
 
 inline const CharacterInfo&
@@ -125,67 +124,76 @@ CharInfo(char16_t code)
 
     return js_charinfo[index];
 }
 
 inline bool
 IsIdentifierStart(char16_t ch)
 {
     /*
-     * ES5 7.6 IdentifierStart
+     * ES2016 11.6 IdentifierStart
      *  $ (dollar sign)
      *  _ (underscore)
-     *  or any UnicodeLetter.
+     *  or any character with the Unicode property «ID_Start».
      *
      * We use a lookup table for small and thus common characters for speed.
      */
 
     if (ch < 128)
         return js_isidstart[ch];
 
-    return CharInfo(ch).isLetter();
+    return CharInfo(ch).isUnicodeIDStart();
 }
 
 inline bool
 IsIdentifierStart(uint32_t codePoint)
 {
     // TODO: Supplemental code points not yet supported (bug 1197230).
     return codePoint <= UTF16Max && IsIdentifierStart(char16_t(codePoint));
 }
 
 inline bool
 IsIdentifierPart(char16_t ch)
 {
-    /* Matches ES5 7.6 IdentifierPart. */
+    /*
+     * ES2016 11.6 IdentifierPart
+     *  $ (dollar sign)
+     *  _ (underscore)
+     *  <ZWNJ>
+     *  <ZWJ>
+     *  or any character with the Unicode property «ID_Continue».
+     *
+     * We use a lookup table for small and thus common characters for speed.
+     */
 
     if (ch < 128)
         return js_isident[ch];
 
-    return CharInfo(ch).isIdentifierPart();
+    return CharInfo(ch).isUnicodeIDContinue();
 }
 
 inline bool
 IsIdentifierPart(uint32_t codePoint)
 {
     // TODO: Supplemental code points not yet supported (bug 1197230).
     return codePoint <= UTF16Max && IsIdentifierPart(char16_t(codePoint));
 }
 
 inline bool
-IsLetter(char16_t ch)
+IsUnicodeIDStart(char16_t ch)
 {
-    return CharInfo(ch).isLetter();
+    return CharInfo(ch).isUnicodeIDStart();
 }
 
 inline bool
 IsSpace(char16_t ch)
 {
     /*
      * IsSpace checks if some character is included in the merged set
-     * of WhiteSpace and LineTerminator, specified by ES5 7.2 and 7.3.
+     * of WhiteSpace and LineTerminator, specified by ES2016 11.2 and 11.3.
      * We combined them, because in practice nearly every
      * calling function wants this, except some code in the tokenizer.
      *
      * We use a lookup table for ASCII-7 characters, because they are
      * very common and must be handled quickly in the tokenizer.
      * NO-BREAK SPACE is supposed to be the most common character not in
      * this range, so we inline this case, too.
      */
--- a/js/src/vm/make_unicode.py
+++ b/js/src/vm/make_unicode.py
@@ -49,18 +49,18 @@ line_terminator = [
 
 # These are also part of IdentifierPart §11.6 Names and Keywords
 compatibility_identifier_part = [
     ord(u'\N{ZERO WIDTH NON-JOINER}'),
     ord(u'\N{ZERO WIDTH JOINER}'),
 ]
 
 FLAG_SPACE = 1 << 0
-FLAG_LETTER = 1 << 1
-FLAG_IDENTIFIER_PART = 1 << 2
+FLAG_UNICODE_ID_START = 1 << 1
+FLAG_UNICODE_ID_CONTINUE_ONLY = 1 << 2
 
 MAX_BMP = 0xffff
 
 public_domain = """
 /*
  * Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/licenses/publicdomain/
  */
@@ -118,16 +118,30 @@ def read_case_folding(case_folding):
             continue
         row = line.split('; ')
         if row[1] in ['F', 'T']:
             continue
         row[0] = int(row[0], 16)
         row[2] = int(row[2], 16)
         yield row
 
+def read_derived_core_properties(derived_core_properties):
+    for line in derived_core_properties:
+        if line == '\n' or line.startswith('#'):
+            continue
+        row = line.split('#')[0].split(';')
+        char_range = row[0].strip()
+        char_property = row[1].strip()
+        if '..' not in char_range:
+            yield (int(char_range, 16), char_property)
+        else:
+            [start, end] = char_range.split('..')
+            for char in range(int(start, 16), int(end, 16) + 1):
+                yield (char, char_property)
+
 def utf16_encode(code):
     NonBMPMin = 0x10000
     LeadSurrogateMin = 0xD800
     TrailSurrogateMin = 0xDC00
 
     lead = (code - NonBMPMin) / 1024 + LeadSurrogateMin
     trail = ((code - NonBMPMin) % 1024) + TrailSurrogateMin
 
@@ -160,33 +174,47 @@ def make_non_bmp_convert_macro(out_file,
 
         lines.append('    macro(0x{:x}, 0x{:x}, 0x{:x}, 0x{:x}, 0x{:x}, {:d})'.format(
             from_code, to_code, from_lead, from_trail, to_trail, diff))
 
     out_file.write('#define FOR_EACH_NON_BMP_{}(macro) \\\n'.format(name))
     out_file.write(' \\\n'.join(lines))
     out_file.write('\n')
 
-def process_unicode_data(unicode_data):
+def process_derived_core_properties(derived_core_properties):
+    id_start = set()
+    id_continue = set()
+
+    for (char, prop) in read_derived_core_properties(derived_core_properties):
+        if prop == 'ID_Start':
+            id_start.add(char)
+        if prop == 'ID_Continue':
+            id_continue.add(char)
+
+    return (id_start, id_continue)
+
+def process_unicode_data(unicode_data, derived_core_properties):
     dummy = (0, 0, 0)
     table = [dummy]
     cache = {dummy: 0}
     index = [0] * (MAX_BMP + 1)
     same_upper_map = {}
     same_upper_dummy = (0, 0, 0)
     same_upper_table = [same_upper_dummy]
     same_upper_cache = {same_upper_dummy: 0}
     same_upper_index = [0] * (MAX_BMP + 1)
 
     test_table = {}
     test_space_table = []
 
     non_bmp_lower_map = {}
     non_bmp_upper_map = {}
 
+    (id_start, id_continue) = process_derived_core_properties(derived_core_properties)
+
     for row in read_unicode_data(unicode_data):
         code = row[0]
         name = row[1]
         category = row[2]
         alias = row[-5]
         uppercase = row[-3]
         lowercase = row[-2]
         flags = 0
@@ -213,23 +241,23 @@ def process_unicode_data(unicode_data):
                 non_bmp_upper_map[code] = upper
             continue
 
         # we combine whitespace and lineterminators because in pratice we don't need them separated
         if category == 'Zs' or code in whitespace or code in line_terminator:
             flags |= FLAG_SPACE
             test_space_table.append(code)
 
-        # §7.6 (UnicodeLetter)
-        if category in ['Lu', 'Ll', 'Lt', 'Lm', 'Lo', 'Nl']:
-            flags |= FLAG_LETTER
+        # §11.6 (IdentifierStart)
+        if code in id_start:
+            flags |= FLAG_UNICODE_ID_START
 
-        # §7.6 (IdentifierPart)
-        if category in ['Mn', 'Mc', 'Nd', 'Pc'] or code in compatibility_identifier_part:
-            flags |= FLAG_IDENTIFIER_PART
+        # §11.6 (IdentifierPart)
+        elif code in id_continue or code in compatibility_identifier_part:
+            flags |= FLAG_UNICODE_ID_CONTINUE_ONLY
 
         test_table[code] = (upper, lower, name, alias)
 
         up_d = upper - code
         low_d = lower - code
 
         assert up_d > -65535 and up_d < 65535
         assert low_d > -65535 and low_d < 65535
@@ -781,17 +809,17 @@ def update_unicode(args):
         casefold_version = version_from_file(case_folding, 'CaseFolding')
 
         print('Processing...')
         (
             table, index,
             same_upper_table, same_upper_index,
             non_bmp_lower_map, non_bmp_upper_map,
             test_table, test_space_table
-        ) = process_unicode_data(unicode_data)
+        ) = process_unicode_data(unicode_data, derived_core_properties)
         (
             folding_table, folding_index,
             non_bmp_folding_map, non_bmp_rev_folding_map,
             folding_tests
         ) = process_case_folding(case_folding)
 
     print('Generating...')
     make_unicode_file(version, casefold_version,