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 351644 483dc75949fa15e328523b383ab4377ee50d753f
parent 351643 816fef70c11d709995182ac7c11c13bea7ac0b62
child 351645 788b95bf4ea32c2684fb30eb719ed1b078dcd3df
push id6795
push userjlund@mozilla.com
push dateMon, 23 Jan 2017 14:19:46 +0000
treeherdermozilla-esr52@76101b503191 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersarai
bugs917436
milestone52.0a1
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,