📄 index.umd.js
/home/palash/git/site/node_modules/re2js/build/index.umd.js
Language: js • Lines: 5798
/*!
 * re2js
 * RE2JS is the JavaScript port of RE2, a regular expression engine that provides linear time matching
 *
 * @version v0.4.3
 * @author Alexey Vasiliev
 * @homepage https://github.com/le0pard/re2js#readme
 * @repository github:le0pard/re2js
 * @license MIT
 */
(function (global, factory) {
  typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
  typeof define === 'function' && define.amd ? define(['exports'], factory) :
  (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.RE2JS = {}));
})(this, (function (exports) { 'use strict';

  //// Parser flags.
  class RE2Flags {
    // Fold case during matching (case-insensitive).
    static FOLD_CASE = 0x01;
    // Treat pattern as a literal string instead of a regexp.
    static LITERAL = 0x02;
    // Allow character classes like [^a-z] and [[:space:]] to match newline.
    static CLASS_NL = 0x04;
    // Allow '.' to match newline.
    static DOT_NL = 0x08;
    // Treat ^ and $ as only matching at beginning and end of text, not
    // around embedded newlines.  (Perl's default).
    static ONE_LINE = 0x10;
    // Make repetition operators default to non-greedy.
    static NON_GREEDY = 0x20;
    // allow Perl extensions:
    //   non-capturing parens - (?: )
    //   non-greedy operators - *? +? ?? {}?
    //   flag edits - (?i) (?-i) (?i: )
    //     i - FoldCase
    //     m - !OneLine
    //     s - DotNL
    //     U - NonGreedy
    //   line ends: \A \z
    //   \Q and \E to disable/enable metacharacters
    //   (?P<name>expr) for named captures
    // \C (any byte) is not supported.
    static PERL_X = 0x40;
    // Allow \p{Han}, \P{Han} for Unicode group and negation.
    static UNICODE_GROUPS = 0x80;
    // Regexp END_TEXT was $, not \z.  Internal use only.
    static WAS_DOLLAR = 0x100;
    static MATCH_NL = (() => RE2Flags.CLASS_NL | RE2Flags.DOT_NL)();
    // As close to Perl as possible.
    static PERL = (() => RE2Flags.CLASS_NL | RE2Flags.ONE_LINE | RE2Flags.PERL_X | RE2Flags.UNICODE_GROUPS)();
    // POSIX syntax.
    static POSIX = 0;
    //// Anchors
    static UNANCHORED = 0;
    static ANCHOR_START = 1;
    static ANCHOR_BOTH = 2;
  }

  /**
   * Various constants and helper for unicode codepoints.
   */
  class Codepoint {
    // codePointAt(0)
    static CODES = (() => new Map([['\x07', 7], ['\b', 8], ['\t', 9], ['\n', 10], ['\v', 11], ['\f', 12], ['\r', 13], [' ', 32], ['"', 34], ['$', 36], ['&', 38], ['(', 40], [')', 41], ['*', 42], ['+', 43], ['-', 45], ['.', 46], ['0', 48], ['1', 49], ['2', 50], ['3', 51], ['4', 52], ['5', 53], ['6', 54], ['7', 55], ['8', 56], ['9', 57], [':', 58], ['<', 60], ['>', 62], ['?', 63], ['A', 65], ['B', 66], ['C', 67], ['F', 70], ['P', 80], ['Q', 81], ['U', 85], ['Z', 90], ['[', 91], ['\\', 92], [']', 93], ['^', 94], ['_', 95], ['a', 97], ['b', 98], ['f', 102], ['i', 105], ['m', 109], ['n', 110], ['r', 114], ['s', 115], ['t', 116], ['v', 118], ['x', 120], ['z', 122], ['{', 123], ['|', 124], ['}', 125]]))();

    // convert unicode codepoint to upper case codepoint
    // return same codepoint, if cannot do it (or codepoint not have upper variation)
    static toUpperCase(codepoint) {
      const s = String.fromCodePoint(codepoint).toUpperCase();
      if (s.length > 1) {
        return codepoint;
      }
      const sOrigin = String.fromCodePoint(s.codePointAt(0)).toLowerCase();
      if (sOrigin.length > 1 || sOrigin.codePointAt(0) !== codepoint) {
        return codepoint;
      }
      return s.codePointAt(0);
    }

    // convert unicode codepoint to lower case codepoint
    // return same codepoint, if cannot do it (or codepoint not have lower variation)
    static toLowerCase(codepoint) {
      const s = String.fromCodePoint(codepoint).toLowerCase();
      if (s.length > 1) {
        return codepoint;
      }
      const sOrigin = String.fromCodePoint(s.codePointAt(0)).toUpperCase();
      if (sOrigin.length > 1 || sOrigin.codePointAt(0) !== codepoint) {
        return codepoint;
      }
      return s.codePointAt(0);
    }
  }

  // GENERATED BY tools/scripts/genUnicodeTable.js; DO NOT EDIT.
  // yarn node ./tools/scripts/genUnicodeTable.js > src/UnicodeTables.js

  class UnicodeTables {
    static CASE_ORBIT = (() => new Map([[75, 107], [107, 8490], [8490, 75], [83, 115], [115, 383], [383, 83], [181, 924], [924, 956], [956, 181], [197, 229], [229, 8491], [8491, 197], [452, 453], [453, 454], [454, 452], [455, 456], [456, 457], [457, 455], [458, 459], [459, 460], [460, 458], [497, 498], [498, 499], [499, 497], [837, 921], [921, 953], [953, 8126], [8126, 837], [914, 946], [946, 976], [976, 914], [917, 949], [949, 1013], [1013, 917], [920, 952], [952, 977], [977, 1012], [1012, 920], [922, 954], [954, 1008], [1008, 922], [928, 960], [960, 982], [982, 928], [929, 961], [961, 1009], [1009, 929], [931, 962], [962, 963], [963, 931], [934, 966], [966, 981], [981, 934], [937, 969], [969, 8486], [8486, 937], [1042, 1074], [1074, 7296], [7296, 1042], [1044, 1076], [1076, 7297], [7297, 1044], [1054, 1086], [1086, 7298], [7298, 1054], [1057, 1089], [1089, 7299], [7299, 1057], [1058, 1090], [1090, 7300], [7300, 7301], [7301, 1058], [1066, 1098], [1098, 7302], [7302, 1066], [1122, 1123], [1123, 7303], [7303, 1122], [7304, 42570], [42570, 42571], [42571, 7304], [7776, 7777], [7777, 7835], [7835, 7776], [223, 7838], [7838, 223], [8064, 8072], [8072, 8064], [8065, 8073], [8073, 8065], [8066, 8074], [8074, 8066], [8067, 8075], [8075, 8067], [8068, 8076], [8076, 8068], [8069, 8077], [8077, 8069], [8070, 8078], [8078, 8070], [8071, 8079], [8079, 8071], [8080, 8088], [8088, 8080], [8081, 8089], [8089, 8081], [8082, 8090], [8090, 8082], [8083, 8091], [8091, 8083], [8084, 8092], [8092, 8084], [8085, 8093], [8093, 8085], [8086, 8094], [8094, 8086], [8087, 8095], [8095, 8087], [8096, 8104], [8104, 8096], [8097, 8105], [8105, 8097], [8098, 8106], [8106, 8098], [8099, 8107], [8107, 8099], [8100, 8108], [8108, 8100], [8101, 8109], [8109, 8101], [8102, 8110], [8110, 8102], [8103, 8111], [8111, 8103], [8115, 8124], [8124, 8115], [8131, 8140], [8140, 8131], [912, 8147], [8147, 912], [944, 8163], [8163, 944], [8179, 8188], [8188, 8179], [64261, 64262], [64262, 64261], [66560, 66600], [66600, 66560], [66561, 66601], [66601, 66561], [66562, 66602], [66602, 66562], [66563, 66603], [66603, 66563], [66564, 66604], [66604, 66564], [66565, 66605], [66605, 66565], [66566, 66606], [66606, 66566], [66567, 66607], [66607, 66567], [66568, 66608], [66608, 66568], [66569, 66609], [66609, 66569], [66570, 66610], [66610, 66570], [66571, 66611], [66611, 66571], [66572, 66612], [66612, 66572], [66573, 66613], [66613, 66573], [66574, 66614], [66614, 66574], [66575, 66615], [66615, 66575], [66576, 66616], [66616, 66576], [66577, 66617], [66617, 66577], [66578, 66618], [66618, 66578], [66579, 66619], [66619, 66579], [66580, 66620], [66620, 66580], [66581, 66621], [66621, 66581], [66582, 66622], [66622, 66582], [66583, 66623], [66623, 66583], [66584, 66624], [66624, 66584], [66585, 66625], [66625, 66585], [66586, 66626], [66626, 66586], [66587, 66627], [66627, 66587], [66588, 66628], [66628, 66588], [66589, 66629], [66629, 66589], [66590, 66630], [66630, 66590], [66591, 66631], [66631, 66591], [66592, 66632], [66632, 66592], [66593, 66633], [66633, 66593], [66594, 66634], [66634, 66594], [66595, 66635], [66635, 66595], [66596, 66636], [66636, 66596], [66597, 66637], [66637, 66597], [66598, 66638], [66638, 66598], [66599, 66639], [66639, 66599], [66736, 66776], [66776, 66736], [66737, 66777], [66777, 66737], [66738, 66778], [66778, 66738], [66739, 66779], [66779, 66739], [66740, 66780], [66780, 66740], [66741, 66781], [66781, 66741], [66742, 66782], [66782, 66742], [66743, 66783], [66783, 66743], [66744, 66784], [66784, 66744], [66745, 66785], [66785, 66745], [66746, 66786], [66786, 66746], [66747, 66787], [66787, 66747], [66748, 66788], [66788, 66748], [66749, 66789], [66789, 66749], [66750, 66790], [66790, 66750], [66751, 66791], [66791, 66751], [66752, 66792], [66792, 66752], [66753, 66793], [66793, 66753], [66754, 66794], [66794, 66754], [66755, 66795], [66795, 66755], [66756, 66796], [66796, 66756], [66757, 66797], [66797, 66757], [66758, 66798], [66798, 66758], [66759, 66799], [66799, 66759], [66760, 66800], [66800, 66760], [66761, 66801], [66801, 66761], [66762, 66802], [66802, 66762], [66763, 66803], [66803, 66763], [66764, 66804], [66804, 66764], [66765, 66805], [66805, 66765], [66766, 66806], [66806, 66766], [66767, 66807], [66807, 66767], [66768, 66808], [66808, 66768], [66769, 66809], [66809, 66769], [66770, 66810], [66810, 66770], [66771, 66811], [66811, 66771], [66928, 66967], [66967, 66928], [66929, 66968], [66968, 66929], [66930, 66969], [66969, 66930], [66931, 66970], [66970, 66931], [66932, 66971], [66971, 66932], [66933, 66972], [66972, 66933], [66934, 66973], [66973, 66934], [66935, 66974], [66974, 66935], [66936, 66975], [66975, 66936], [66937, 66976], [66976, 66937], [66938, 66977], [66977, 66938], [66940, 66979], [66979, 66940], [66941, 66980], [66980, 66941], [66942, 66981], [66981, 66942], [66943, 66982], [66982, 66943], [66944, 66983], [66983, 66944], [66945, 66984], [66984, 66945], [66946, 66985], [66985, 66946], [66947, 66986], [66986, 66947], [66948, 66987], [66987, 66948], [66949, 66988], [66988, 66949], [66950, 66989], [66989, 66950], [66951, 66990], [66990, 66951], [66952, 66991], [66991, 66952], [66953, 66992], [66992, 66953], [66954, 66993], [66993, 66954], [66956, 66995], [66995, 66956], [66957, 66996], [66996, 66957], [66958, 66997], [66997, 66958], [66959, 66998], [66998, 66959], [66960, 66999], [66999, 66960], [66961, 67000], [67000, 66961], [66962, 67001], [67001, 66962], [66964, 67003], [67003, 66964], [66965, 67004], [67004, 66965], [68736, 68800], [68800, 68736], [68737, 68801], [68801, 68737], [68738, 68802], [68802, 68738], [68739, 68803], [68803, 68739], [68740, 68804], [68804, 68740], [68741, 68805], [68805, 68741], [68742, 68806], [68806, 68742], [68743, 68807], [68807, 68743], [68744, 68808], [68808, 68744], [68745, 68809], [68809, 68745], [68746, 68810], [68810, 68746], [68747, 68811], [68811, 68747], [68748, 68812], [68812, 68748], [68749, 68813], [68813, 68749], [68750, 68814], [68814, 68750], [68751, 68815], [68815, 68751], [68752, 68816], [68816, 68752], [68753, 68817], [68817, 68753], [68754, 68818], [68818, 68754], [68755, 68819], [68819, 68755], [68756, 68820], [68820, 68756], [68757, 68821], [68821, 68757], [68758, 68822], [68822, 68758], [68759, 68823], [68823, 68759], [68760, 68824], [68824, 68760], [68761, 68825], [68825, 68761], [68762, 68826], [68826, 68762], [68763, 68827], [68827, 68763], [68764, 68828], [68828, 68764], [68765, 68829], [68829, 68765], [68766, 68830], [68830, 68766], [68767, 68831], [68831, 68767], [68768, 68832], [68832, 68768], [68769, 68833], [68833, 68769], [68770, 68834], [68834, 68770], [68771, 68835], [68835, 68771], [68772, 68836], [68836, 68772], [68773, 68837], [68837, 68773], [68774, 68838], [68838, 68774], [68775, 68839], [68839, 68775], [68776, 68840], [68840, 68776], [68777, 68841], [68841, 68777], [68778, 68842], [68842, 68778], [68779, 68843], [68843, 68779], [68780, 68844], [68844, 68780], [68781, 68845], [68845, 68781], [68782, 68846], [68846, 68782], [68783, 68847], [68847, 68783], [68784, 68848], [68848, 68784], [68785, 68849], [68849, 68785], [68786, 68850], [68850, 68786], [71840, 71872], [71872, 71840], [71841, 71873], [71873, 71841], [71842, 71874], [71874, 71842], [71843, 71875], [71875, 71843], [71844, 71876], [71876, 71844], [71845, 71877], [71877, 71845], [71846, 71878], [71878, 71846], [71847, 71879], [71879, 71847], [71848, 71880], [71880, 71848], [71849, 71881], [71881, 71849], [71850, 71882], [71882, 71850], [71851, 71883], [71883, 71851], [71852, 71884], [71884, 71852], [71853, 71885], [71885, 71853], [71854, 71886], [71886, 71854], [71855, 71887], [71887, 71855], [71856, 71888], [71888, 71856], [71857, 71889], [71889, 71857], [71858, 71890], [71890, 71858], [71859, 71891], [71891, 71859], [71860, 71892], [71892, 71860], [71861, 71893], [71893, 71861], [71862, 71894], [71894, 71862], [71863, 71895], [71895, 71863], [71864, 71896], [71896, 71864], [71865, 71897], [71897, 71865], [71866, 71898], [71898, 71866], [71867, 71899], [71899, 71867], [71868, 71900], [71900, 71868], [71869, 71901], [71901, 71869], [71870, 71902], [71902, 71870], [71871, 71903], [71903, 71871], [93760, 93792], [93792, 93760], [93761, 93793], [93793, 93761], [93762, 93794], [93794, 93762], [93763, 93795], [93795, 93763], [93764, 93796], [93796, 93764], [93765, 93797], [93797, 93765], [93766, 93798], [93798, 93766], [93767, 93799], [93799, 93767], [93768, 93800], [93800, 93768], [93769, 93801], [93801, 93769], [93770, 93802], [93802, 93770], [93771, 93803], [93803, 93771], [93772, 93804], [93804, 93772], [93773, 93805], [93805, 93773], [93774, 93806], [93806, 93774], [93775, 93807], [93807, 93775], [93776, 93808], [93808, 93776], [93777, 93809], [93809, 93777], [93778, 93810], [93810, 93778], [93779, 93811], [93811, 93779], [93780, 93812], [93812, 93780], [93781, 93813], [93813, 93781], [93782, 93814], [93814, 93782], [93783, 93815], [93815, 93783], [93784, 93816], [93816, 93784], [93785, 93817], [93817, 93785], [93786, 93818], [93818, 93786], [93787, 93819], [93819, 93787], [93788, 93820], [93820, 93788], [93789, 93821], [93821, 93789], [93790, 93822], [93822, 93790], [93791, 93823], [93823, 93791], [125184, 125218], [125218, 125184], [125185, 125219], [125219, 125185], [125186, 125220], [125220, 125186], [125187, 125221], [125221, 125187], [125188, 125222], [125222, 125188], [125189, 125223], [125223, 125189], [125190, 125224], [125224, 125190], [125191, 125225], [125225, 125191], [125192, 125226], [125226, 125192], [125193, 125227], [125227, 125193], [125194, 125228], [125228, 125194], [125195, 125229], [125229, 125195], [125196, 125230], [125230, 125196], [125197, 125231], [125231, 125197], [125198, 125232], [125232, 125198], [125199, 125233], [125233, 125199], [125200, 125234], [125234, 125200], [125201, 125235], [125235, 125201], [125202, 125236], [125236, 125202], [125203, 125237], [125237, 125203], [125204, 125238], [125238, 125204], [125205, 125239], [125239, 125205], [125206, 125240], [125240, 125206], [125207, 125241], [125241, 125207], [125208, 125242], [125242, 125208], [125209, 125243], [125243, 125209], [125210, 125244], [125244, 125210], [125211, 125245], [125245, 125211], [125212, 125246], [125246, 125212], [125213, 125247], [125247, 125213], [125214, 125248], [125248, 125214], [125215, 125249], [125249, 125215], [125216, 125250], [125250, 125216], [125217, 125251], [125251, 125217]]))();
    static C = [[0, 31, 1], [127, 159, 1], [173, 888, 715], [889, 896, 7], [897, 899, 1], [907, 909, 2], [930, 1328, 398], [1367, 1368, 1], [1419, 1420, 1], [1424, 1480, 56], [1481, 1487, 1], [1515, 1518, 1], [1525, 1541, 1], [1564, 1757, 193], [1806, 1807, 1], [1867, 1868, 1], [1970, 1983, 1], [2043, 2044, 1], [2094, 2095, 1], [2111, 2140, 29], [2141, 2143, 2], [2155, 2159, 1], [2191, 2199, 1], [2274, 2436, 162], [2445, 2446, 1], [2449, 2450, 1], [2473, 2481, 8], [2483, 2485, 1], [2490, 2491, 1], [2501, 2502, 1], [2505, 2506, 1], [2511, 2518, 1], [2520, 2523, 1], [2526, 2532, 6], [2533, 2559, 26], [2560, 2564, 4], [2571, 2574, 1], [2577, 2578, 1], [2601, 2609, 8], [2612, 2618, 3], [2619, 2621, 2], [2627, 2630, 1], [2633, 2634, 1], [2638, 2640, 1], [2642, 2648, 1], [2653, 2655, 2], [2656, 2661, 1], [2679, 2688, 1], [2692, 2702, 10], [2706, 2729, 23], [2737, 2740, 3], [2746, 2747, 1], [2758, 2766, 4], [2767, 2769, 2], [2770, 2783, 1], [2788, 2789, 1], [2802, 2808, 1], [2816, 2820, 4], [2829, 2830, 1], [2833, 2834, 1], [2857, 2865, 8], [2868, 2874, 6], [2875, 2885, 10], [2886, 2889, 3], [2890, 2894, 4], [2895, 2900, 1], [2904, 2907, 1], [2910, 2916, 6], [2917, 2936, 19], [2937, 2945, 1], [2948, 2955, 7], [2956, 2957, 1], [2961, 2966, 5], [2967, 2968, 1], [2971, 2973, 2], [2976, 2978, 1], [2981, 2983, 1], [2987, 2989, 1], [3002, 3005, 1], [3011, 3013, 1], [3017, 3022, 5], [3023, 3025, 2], [3026, 3030, 1], [3032, 3045, 1], [3067, 3071, 1], [3085, 3089, 4], [3113, 3130, 17], [3131, 3141, 10], [3145, 3150, 5], [3151, 3156, 1], [3159, 3163, 4], [3164, 3166, 2], [3167, 3172, 5], [3173, 3184, 11], [3185, 3190, 1], [3213, 3217, 4], [3241, 3252, 11], [3258, 3259, 1], [3269, 3273, 4], [3278, 3284, 1], [3287, 3292, 1], [3295, 3300, 5], [3301, 3312, 11], [3316, 3327, 1], [3341, 3345, 4], [3397, 3401, 4], [3408, 3411, 1], [3428, 3429, 1], [3456, 3460, 4], [3479, 3481, 1], [3506, 3516, 10], [3518, 3519, 1], [3527, 3529, 1], [3531, 3534, 1], [3541, 3543, 2], [3552, 3557, 1], [3568, 3569, 1], [3573, 3584, 1], [3643, 3646, 1], [3676, 3712, 1], [3715, 3717, 2], [3723, 3748, 25], [3750, 3774, 24], [3775, 3781, 6], [3783, 3791, 8], [3802, 3803, 1], [3808, 3839, 1], [3912, 3949, 37], [3950, 3952, 1], [3992, 4029, 37], [4045, 4059, 14], [4060, 4095, 1], [4294, 4296, 2], [4297, 4300, 1], [4302, 4303, 1], [4681, 4686, 5], [4687, 4695, 8], [4697, 4702, 5], [4703, 4745, 42], [4750, 4751, 1], [4785, 4790, 5], [4791, 4799, 8], [4801, 4806, 5], [4807, 4823, 16], [4881, 4886, 5], [4887, 4955, 68], [4956, 4989, 33], [4990, 4991, 1], [5018, 5023, 1], [5110, 5111, 1], [5118, 5119, 1], [5789, 5791, 1], [5881, 5887, 1], [5910, 5918, 1], [5943, 5951, 1], [5972, 5983, 1], [5997, 6001, 4], [6004, 6015, 1], [6110, 6111, 1], [6122, 6127, 1], [6138, 6143, 1], [6158, 6170, 12], [6171, 6175, 1], [6265, 6271, 1], [6315, 6319, 1], [6390, 6399, 1], [6431, 6444, 13], [6445, 6447, 1], [6460, 6463, 1], [6465, 6467, 1], [6510, 6511, 1], [6517, 6527, 1], [6572, 6575, 1], [6602, 6607, 1], [6619, 6621, 1], [6684, 6685, 1], [6751, 6781, 30], [6782, 6794, 12], [6795, 6799, 1], [6810, 6815, 1], [6830, 6831, 1], [6863, 6911, 1], [6989, 6991, 1], [7039, 7156, 117], [7157, 7163, 1], [7224, 7226, 1], [7242, 7244, 1], [7305, 7311, 1], [7355, 7356, 1], [7368, 7375, 1], [7419, 7423, 1], [7958, 7959, 1], [7966, 7967, 1], [8006, 8007, 1], [8014, 8015, 1], [8024, 8030, 2], [8062, 8063, 1], [8117, 8133, 16], [8148, 8149, 1], [8156, 8176, 20], [8177, 8181, 4], [8191, 8203, 12], [8204, 8207, 1], [8234, 8238, 1], [8288, 8303, 1], [8306, 8307, 1], [8335, 8349, 14], [8350, 8351, 1], [8385, 8399, 1], [8433, 8447, 1], [8588, 8591, 1], [9255, 9279, 1], [9291, 9311, 1], [11124, 11125, 1], [11158, 11508, 350], [11509, 11512, 1], [11558, 11560, 2], [11561, 11564, 1], [11566, 11567, 1], [11624, 11630, 1], [11633, 11646, 1], [11671, 11679, 1], [11687, 11743, 8], [11870, 11903, 1], [11930, 12020, 90], [12021, 12031, 1], [12246, 12271, 1], [12352, 12439, 87], [12440, 12544, 104], [12545, 12548, 1], [12592, 12687, 95], [12772, 12782, 1], [12831, 42125, 29294], [42126, 42127, 1], [42183, 42191, 1], [42540, 42559, 1], [42744, 42751, 1], [42955, 42959, 1], [42962, 42964, 2], [42970, 42993, 1], [43053, 43055, 1], [43066, 43071, 1], [43128, 43135, 1], [43206, 43213, 1], [43226, 43231, 1], [43348, 43358, 1], [43389, 43391, 1], [43470, 43482, 12], [43483, 43485, 1], [43519, 43575, 56], [43576, 43583, 1], [43598, 43599, 1], [43610, 43611, 1], [43715, 43738, 1], [43767, 43776, 1], [43783, 43784, 1], [43791, 43792, 1], [43799, 43807, 1], [43815, 43823, 8], [43884, 43887, 1], [44014, 44015, 1], [44026, 44031, 1], [55204, 55215, 1], [55239, 55242, 1], [55292, 63743, 1], [64110, 64111, 1], [64218, 64255, 1], [64263, 64274, 1], [64280, 64284, 1], [64311, 64317, 6], [64319, 64325, 3], [64451, 64466, 1], [64912, 64913, 1], [64968, 64974, 1], [64976, 65007, 1], [65050, 65055, 1], [65107, 65127, 20], [65132, 65135, 1], [65141, 65277, 136], [65278, 65280, 1], [65471, 65473, 1], [65480, 65481, 1], [65488, 65489, 1], [65496, 65497, 1], [65501, 65503, 1], [65511, 65519, 8], [65520, 65531, 1], [65534, 65535, 1], [65548, 65575, 27], [65595, 65598, 3], [65614, 65615, 1], [65630, 65663, 1], [65787, 65791, 1], [65795, 65798, 1], [65844, 65846, 1], [65935, 65949, 14], [65950, 65951, 1], [65953, 65999, 1], [66046, 66175, 1], [66205, 66207, 1], [66257, 66271, 1], [66300, 66303, 1], [66340, 66348, 1], [66379, 66383, 1], [66427, 66431, 1], [66462, 66500, 38], [66501, 66503, 1], [66518, 66559, 1], [66718, 66719, 1], [66730, 66735, 1], [66772, 66775, 1], [66812, 66815, 1], [66856, 66863, 1], [66916, 66926, 1], [66939, 66955, 16], [66963, 66966, 3], [66978, 66994, 16], [67002, 67005, 3], [67006, 67071, 1], [67383, 67391, 1], [67414, 67423, 1], [67432, 67455, 1], [67462, 67505, 43], [67515, 67583, 1], [67590, 67591, 1], [67593, 67638, 45], [67641, 67643, 1], [67645, 67646, 1], [67670, 67743, 73], [67744, 67750, 1], [67760, 67807, 1], [67827, 67830, 3], [67831, 67834, 1], [67868, 67870, 1], [67898, 67902, 1], [67904, 67967, 1], [68024, 68027, 1], [68048, 68049, 1], [68100, 68103, 3], [68104, 68107, 1], [68116, 68120, 4], [68150, 68151, 1], [68155, 68158, 1], [68169, 68175, 1], [68185, 68191, 1], [68256, 68287, 1], [68327, 68330, 1], [68343, 68351, 1], [68406, 68408, 1], [68438, 68439, 1], [68467, 68471, 1], [68498, 68504, 1], [68509, 68520, 1], [68528, 68607, 1], [68681, 68735, 1], [68787, 68799, 1], [68851, 68857, 1], [68904, 68911, 1], [68922, 69215, 1], [69247, 69290, 43], [69294, 69295, 1], [69298, 69372, 1], [69416, 69423, 1], [69466, 69487, 1], [69514, 69551, 1], [69580, 69599, 1], [69623, 69631, 1], [69710, 69713, 1], [69750, 69758, 1], [69821, 69827, 6], [69828, 69839, 1], [69865, 69871, 1], [69882, 69887, 1], [69941, 69960, 19], [69961, 69967, 1], [70007, 70015, 1], [70112, 70133, 21], [70134, 70143, 1], [70162, 70210, 48], [70211, 70271, 1], [70279, 70281, 2], [70286, 70302, 16], [70314, 70319, 1], [70379, 70383, 1], [70394, 70399, 1], [70404, 70413, 9], [70414, 70417, 3], [70418, 70441, 23], [70449, 70452, 3], [70458, 70469, 11], [70470, 70473, 3], [70474, 70478, 4], [70479, 70481, 2], [70482, 70486, 1], [70488, 70492, 1], [70500, 70501, 1], [70509, 70511, 1], [70517, 70655, 1], [70748, 70754, 6], [70755, 70783, 1], [70856, 70863, 1], [70874, 71039, 1], [71094, 71095, 1], [71134, 71167, 1], [71237, 71247, 1], [71258, 71263, 1], [71277, 71295, 1], [71354, 71359, 1], [71370, 71423, 1], [71451, 71452, 1], [71468, 71471, 1], [71495, 71679, 1], [71740, 71839, 1], [71923, 71934, 1], [71943, 71944, 1], [71946, 71947, 1], [71956, 71959, 3], [71990, 71993, 3], [71994, 72007, 13], [72008, 72015, 1], [72026, 72095, 1], [72104, 72105, 1], [72152, 72153, 1], [72165, 72191, 1], [72264, 72271, 1], [72355, 72367, 1], [72441, 72447, 1], [72458, 72703, 1], [72713, 72759, 46], [72774, 72783, 1], [72813, 72815, 1], [72848, 72849, 1], [72872, 72887, 15], [72888, 72959, 1], [72967, 72970, 3], [73015, 73017, 1], [73019, 73022, 3], [73032, 73039, 1], [73050, 73055, 1], [73062, 73065, 3], [73103, 73106, 3], [73113, 73119, 1], [73130, 73439, 1], [73465, 73471, 1], [73489, 73531, 42], [73532, 73533, 1], [73562, 73647, 1], [73649, 73663, 1], [73714, 73726, 1], [74650, 74751, 1], [74863, 74869, 6], [74870, 74879, 1], [75076, 77711, 1], [77811, 77823, 1], [78896, 78911, 1], [78934, 82943, 1], [83527, 92159, 1], [92729, 92735, 1], [92767, 92778, 11], [92779, 92781, 1], [92863, 92874, 11], [92875, 92879, 1], [92910, 92911, 1], [92918, 92927, 1], [92998, 93007, 1], [93018, 93026, 8], [93048, 93052, 1], [93072, 93759, 1], [93851, 93951, 1], [94027, 94030, 1], [94088, 94094, 1], [94112, 94175, 1], [94181, 94191, 1], [94194, 94207, 1], [100344, 100351, 1], [101590, 101631, 1], [101641, 110575, 1], [110580, 110588, 8], [110591, 110883, 292], [110884, 110897, 1], [110899, 110927, 1], [110931, 110932, 1], [110934, 110947, 1], [110952, 110959, 1], [111356, 113663, 1], [113771, 113775, 1], [113789, 113791, 1], [113801, 113807, 1], [113818, 113819, 1], [113824, 118527, 1], [118574, 118575, 1], [118599, 118607, 1], [118724, 118783, 1], [119030, 119039, 1], [119079, 119080, 1], [119155, 119162, 1], [119275, 119295, 1], [119366, 119487, 1], [119508, 119519, 1], [119540, 119551, 1], [119639, 119647, 1], [119673, 119807, 1], [119893, 119965, 72], [119968, 119969, 1], [119971, 119972, 1], [119975, 119976, 1], [119981, 119994, 13], [119996, 120004, 8], [120070, 120075, 5], [120076, 120085, 9], [120093, 120122, 29], [120127, 120133, 6], [120135, 120137, 1], [120145, 120486, 341], [120487, 120780, 293], [120781, 121484, 703], [121485, 121498, 1], [121504, 121520, 16], [121521, 122623, 1], [122655, 122660, 1], [122667, 122879, 1], [122887, 122905, 18], [122906, 122914, 8], [122917, 122923, 6], [122924, 122927, 1], [122990, 123022, 1], [123024, 123135, 1], [123181, 123183, 1], [123198, 123199, 1], [123210, 123213, 1], [123216, 123535, 1], [123567, 123583, 1], [123642, 123646, 1], [123648, 124111, 1], [124154, 124895, 1], [124903, 124908, 5], [124911, 124927, 16], [125125, 125126, 1], [125143, 125183, 1], [125260, 125263, 1], [125274, 125277, 1], [125280, 126064, 1], [126133, 126208, 1], [126270, 126463, 1], [126468, 126496, 28], [126499, 126501, 2], [126502, 126504, 2], [126515, 126520, 5], [126522, 126524, 2], [126525, 126529, 1], [126531, 126534, 1], [126536, 126540, 2], [126544, 126547, 3], [126549, 126550, 1], [126552, 126560, 2], [126563, 126565, 2], [126566, 126571, 5], [126579, 126589, 5], [126591, 126602, 11], [126620, 126624, 1], [126628, 126634, 6], [126652, 126703, 1], [126706, 126975, 1], [127020, 127023, 1], [127124, 127135, 1], [127151, 127152, 1], [127168, 127184, 16], [127222, 127231, 1], [127406, 127461, 1], [127491, 127503, 1], [127548, 127551, 1], [127561, 127567, 1], [127570, 127583, 1], [127590, 127743, 1], [128728, 128731, 1], [128749, 128751, 1], [128765, 128767, 1], [128887, 128890, 1], [128986, 128991, 1], [129004, 129007, 1], [129009, 129023, 1], [129036, 129039, 1], [129096, 129103, 1], [129114, 129119, 1], [129160, 129167, 1], [129198, 129199, 1], [129202, 129279, 1], [129620, 129631, 1], [129646, 129647, 1], [129661, 129663, 1], [129673, 129679, 1], [129726, 129734, 8], [129735, 129741, 1], [129756, 129759, 1], [129769, 129775, 1], [129785, 129791, 1], [129939, 129995, 56], [129996, 130031, 1], [130042, 131071, 1], [173792, 173823, 1], [177978, 177983, 1], [178206, 178207, 1], [183970, 183983, 1], [191457, 191471, 1], [192094, 194559, 1], [195102, 196607, 1], [201547, 201551, 1], [205744, 917759, 1], [918000, 1114111, 1]];
    static Cc = [[0, 31, 1], [127, 159, 1]];
    static Cf = [[173, 1536, 1363], [1537, 1541, 1], [1564, 1757, 193], [1807, 2192, 385], [2193, 2274, 81], [6158, 8203, 2045], [8204, 8207, 1], [8234, 8238, 1], [8288, 8292, 1], [8294, 8303, 1], [65279, 65529, 250], [65530, 65531, 1], [69821, 69837, 16], [78896, 78911, 1], [113824, 113827, 1], [119155, 119162, 1], [917505, 917536, 31], [917537, 917631, 1]];
    static Co = [[57344, 63743, 1], [983040, 1048573, 1], [1048576, 1114109, 1]];
    static Cs = [[55296, 57343, 1]];
    static L = [[65, 90, 1], [97, 122, 1], [170, 181, 11], [186, 192, 6], [193, 214, 1], [216, 246, 1], [248, 705, 1], [710, 721, 1], [736, 740, 1], [748, 750, 2], [880, 884, 1], [886, 887, 1], [890, 893, 1], [895, 902, 7], [904, 906, 1], [908, 910, 2], [911, 929, 1], [931, 1013, 1], [1015, 1153, 1], [1162, 1327, 1], [1329, 1366, 1], [1369, 1376, 7], [1377, 1416, 1], [1488, 1514, 1], [1519, 1522, 1], [1568, 1610, 1], [1646, 1647, 1], [1649, 1747, 1], [1749, 1765, 16], [1766, 1774, 8], [1775, 1786, 11], [1787, 1788, 1], [1791, 1808, 17], [1810, 1839, 1], [1869, 1957, 1], [1969, 1994, 25], [1995, 2026, 1], [2036, 2037, 1], [2042, 2048, 6], [2049, 2069, 1], [2074, 2084, 10], [2088, 2112, 24], [2113, 2136, 1], [2144, 2154, 1], [2160, 2183, 1], [2185, 2190, 1], [2208, 2249, 1], [2308, 2361, 1], [2365, 2384, 19], [2392, 2401, 1], [2417, 2432, 1], [2437, 2444, 1], [2447, 2448, 1], [2451, 2472, 1], [2474, 2480, 1], [2482, 2486, 4], [2487, 2489, 1], [2493, 2510, 17], [2524, 2525, 1], [2527, 2529, 1], [2544, 2545, 1], [2556, 2565, 9], [2566, 2570, 1], [2575, 2576, 1], [2579, 2600, 1], [2602, 2608, 1], [2610, 2611, 1], [2613, 2614, 1], [2616, 2617, 1], [2649, 2652, 1], [2654, 2674, 20], [2675, 2676, 1], [2693, 2701, 1], [2703, 2705, 1], [2707, 2728, 1], [2730, 2736, 1], [2738, 2739, 1], [2741, 2745, 1], [2749, 2768, 19], [2784, 2785, 1], [2809, 2821, 12], [2822, 2828, 1], [2831, 2832, 1], [2835, 2856, 1], [2858, 2864, 1], [2866, 2867, 1], [2869, 2873, 1], [2877, 2908, 31], [2909, 2911, 2], [2912, 2913, 1], [2929, 2947, 18], [2949, 2954, 1], [2958, 2960, 1], [2962, 2965, 1], [2969, 2970, 1], [2972, 2974, 2], [2975, 2979, 4], [2980, 2984, 4], [2985, 2986, 1], [2990, 3001, 1], [3024, 3077, 53], [3078, 3084, 1], [3086, 3088, 1], [3090, 3112, 1], [3114, 3129, 1], [3133, 3160, 27], [3161, 3162, 1], [3165, 3168, 3], [3169, 3200, 31], [3205, 3212, 1], [3214, 3216, 1], [3218, 3240, 1], [3242, 3251, 1], [3253, 3257, 1], [3261, 3293, 32], [3294, 3296, 2], [3297, 3313, 16], [3314, 3332, 18], [3333, 3340, 1], [3342, 3344, 1], [3346, 3386, 1], [3389, 3406, 17], [3412, 3414, 1], [3423, 3425, 1], [3450, 3455, 1], [3461, 3478, 1], [3482, 3505, 1], [3507, 3515, 1], [3517, 3520, 3], [3521, 3526, 1], [3585, 3632, 1], [3634, 3635, 1], [3648, 3654, 1], [3713, 3714, 1], [3716, 3718, 2], [3719, 3722, 1], [3724, 3747, 1], [3749, 3751, 2], [3752, 3760, 1], [3762, 3763, 1], [3773, 3776, 3], [3777, 3780, 1], [3782, 3804, 22], [3805, 3807, 1], [3840, 3904, 64], [3905, 3911, 1], [3913, 3948, 1], [3976, 3980, 1], [4096, 4138, 1], [4159, 4176, 17], [4177, 4181, 1], [4186, 4189, 1], [4193, 4197, 4], [4198, 4206, 8], [4207, 4208, 1], [4213, 4225, 1], [4238, 4256, 18], [4257, 4293, 1], [4295, 4301, 6], [4304, 4346, 1], [4348, 4680, 1], [4682, 4685, 1], [4688, 4694, 1], [4696, 4698, 2], [4699, 4701, 1], [4704, 4744, 1], [4746, 4749, 1], [4752, 4784, 1], [4786, 4789, 1], [4792, 4798, 1], [4800, 4802, 2], [4803, 4805, 1], [4808, 4822, 1], [4824, 4880, 1], [4882, 4885, 1], [4888, 4954, 1], [4992, 5007, 1], [5024, 5109, 1], [5112, 5117, 1], [5121, 5740, 1], [5743, 5759, 1], [5761, 5786, 1], [5792, 5866, 1], [5873, 5880, 1], [5888, 5905, 1], [5919, 5937, 1], [5952, 5969, 1], [5984, 5996, 1], [5998, 6000, 1], [6016, 6067, 1], [6103, 6108, 5], [6176, 6264, 1], [6272, 6276, 1], [6279, 6312, 1], [6314, 6320, 6], [6321, 6389, 1], [6400, 6430, 1], [6480, 6509, 1], [6512, 6516, 1], [6528, 6571, 1], [6576, 6601, 1], [6656, 6678, 1], [6688, 6740, 1], [6823, 6917, 94], [6918, 6963, 1], [6981, 6988, 1], [7043, 7072, 1], [7086, 7087, 1], [7098, 7141, 1], [7168, 7203, 1], [7245, 7247, 1], [7258, 7293, 1], [7296, 7304, 1], [7312, 7354, 1], [7357, 7359, 1], [7401, 7404, 1], [7406, 7411, 1], [7413, 7414, 1], [7418, 7424, 6], [7425, 7615, 1], [7680, 7957, 1], [7960, 7965, 1], [7968, 8005, 1], [8008, 8013, 1], [8016, 8023, 1], [8025, 8031, 2], [8032, 8061, 1], [8064, 8116, 1], [8118, 8124, 1], [8126, 8130, 4], [8131, 8132, 1], [8134, 8140, 1], [8144, 8147, 1], [8150, 8155, 1], [8160, 8172, 1], [8178, 8180, 1], [8182, 8188, 1], [8305, 8319, 14], [8336, 8348, 1], [8450, 8455, 5], [8458, 8467, 1], [8469, 8473, 4], [8474, 8477, 1], [8484, 8490, 2], [8491, 8493, 1], [8495, 8505, 1], [8508, 8511, 1], [8517, 8521, 1], [8526, 8579, 53], [8580, 11264, 2684], [11265, 11492, 1], [11499, 11502, 1], [11506, 11507, 1], [11520, 11557, 1], [11559, 11565, 6], [11568, 11623, 1], [11631, 11648, 17], [11649, 11670, 1], [11680, 11686, 1], [11688, 11694, 1], [11696, 11702, 1], [11704, 11710, 1], [11712, 11718, 1], [11720, 11726, 1], [11728, 11734, 1], [11736, 11742, 1], [11823, 12293, 470], [12294, 12337, 43], [12338, 12341, 1], [12347, 12348, 1], [12353, 12438, 1], [12445, 12447, 1], [12449, 12538, 1], [12540, 12543, 1], [12549, 12591, 1], [12593, 12686, 1], [12704, 12735, 1], [12784, 12799, 1], [13312, 19903, 1], [19968, 42124, 1], [42192, 42237, 1], [42240, 42508, 1], [42512, 42527, 1], [42538, 42539, 1], [42560, 42606, 1], [42623, 42653, 1], [42656, 42725, 1], [42775, 42783, 1], [42786, 42888, 1], [42891, 42954, 1], [42960, 42961, 1], [42963, 42965, 2], [42966, 42969, 1], [42994, 43009, 1], [43011, 43013, 1], [43015, 43018, 1], [43020, 43042, 1], [43072, 43123, 1], [43138, 43187, 1], [43250, 43255, 1], [43259, 43261, 2], [43262, 43274, 12], [43275, 43301, 1], [43312, 43334, 1], [43360, 43388, 1], [43396, 43442, 1], [43471, 43488, 17], [43489, 43492, 1], [43494, 43503, 1], [43514, 43518, 1], [43520, 43560, 1], [43584, 43586, 1], [43588, 43595, 1], [43616, 43638, 1], [43642, 43646, 4], [43647, 43695, 1], [43697, 43701, 4], [43702, 43705, 3], [43706, 43709, 1], [43712, 43714, 2], [43739, 43741, 1], [43744, 43754, 1], [43762, 43764, 1], [43777, 43782, 1], [43785, 43790, 1], [43793, 43798, 1], [43808, 43814, 1], [43816, 43822, 1], [43824, 43866, 1], [43868, 43881, 1], [43888, 44002, 1], [44032, 55203, 1], [55216, 55238, 1], [55243, 55291, 1], [63744, 64109, 1], [64112, 64217, 1], [64256, 64262, 1], [64275, 64279, 1], [64285, 64287, 2], [64288, 64296, 1], [64298, 64310, 1], [64312, 64316, 1], [64318, 64320, 2], [64321, 64323, 2], [64324, 64326, 2], [64327, 64433, 1], [64467, 64829, 1], [64848, 64911, 1], [64914, 64967, 1], [65008, 65019, 1], [65136, 65140, 1], [65142, 65276, 1], [65313, 65338, 1], [65345, 65370, 1], [65382, 65470, 1], [65474, 65479, 1], [65482, 65487, 1], [65490, 65495, 1], [65498, 65500, 1], [65536, 65547, 1], [65549, 65574, 1], [65576, 65594, 1], [65596, 65597, 1], [65599, 65613, 1], [65616, 65629, 1], [65664, 65786, 1], [66176, 66204, 1], [66208, 66256, 1], [66304, 66335, 1], [66349, 66368, 1], [66370, 66377, 1], [66384, 66421, 1], [66432, 66461, 1], [66464, 66499, 1], [66504, 66511, 1], [66560, 66717, 1], [66736, 66771, 1], [66776, 66811, 1], [66816, 66855, 1], [66864, 66915, 1], [66928, 66938, 1], [66940, 66954, 1], [66956, 66962, 1], [66964, 66965, 1], [66967, 66977, 1], [66979, 66993, 1], [66995, 67001, 1], [67003, 67004, 1], [67072, 67382, 1], [67392, 67413, 1], [67424, 67431, 1], [67456, 67461, 1], [67463, 67504, 1], [67506, 67514, 1], [67584, 67589, 1], [67592, 67594, 2], [67595, 67637, 1], [67639, 67640, 1], [67644, 67647, 3], [67648, 67669, 1], [67680, 67702, 1], [67712, 67742, 1], [67808, 67826, 1], [67828, 67829, 1], [67840, 67861, 1], [67872, 67897, 1], [67968, 68023, 1], [68030, 68031, 1], [68096, 68112, 16], [68113, 68115, 1], [68117, 68119, 1], [68121, 68149, 1], [68192, 68220, 1], [68224, 68252, 1], [68288, 68295, 1], [68297, 68324, 1], [68352, 68405, 1], [68416, 68437, 1], [68448, 68466, 1], [68480, 68497, 1], [68608, 68680, 1], [68736, 68786, 1], [68800, 68850, 1], [68864, 68899, 1], [69248, 69289, 1], [69296, 69297, 1], [69376, 69404, 1], [69415, 69424, 9], [69425, 69445, 1], [69488, 69505, 1], [69552, 69572, 1], [69600, 69622, 1], [69635, 69687, 1], [69745, 69746, 1], [69749, 69763, 14], [69764, 69807, 1], [69840, 69864, 1], [69891, 69926, 1], [69956, 69959, 3], [69968, 70002, 1], [70006, 70019, 13], [70020, 70066, 1], [70081, 70084, 1], [70106, 70108, 2], [70144, 70161, 1], [70163, 70187, 1], [70207, 70208, 1], [70272, 70278, 1], [70280, 70282, 2], [70283, 70285, 1], [70287, 70301, 1], [70303, 70312, 1], [70320, 70366, 1], [70405, 70412, 1], [70415, 70416, 1], [70419, 70440, 1], [70442, 70448, 1], [70450, 70451, 1], [70453, 70457, 1], [70461, 70480, 19], [70493, 70497, 1], [70656, 70708, 1], [70727, 70730, 1], [70751, 70753, 1], [70784, 70831, 1], [70852, 70853, 1], [70855, 71040, 185], [71041, 71086, 1], [71128, 71131, 1], [71168, 71215, 1], [71236, 71296, 60], [71297, 71338, 1], [71352, 71424, 72], [71425, 71450, 1], [71488, 71494, 1], [71680, 71723, 1], [71840, 71903, 1], [71935, 71942, 1], [71945, 71948, 3], [71949, 71955, 1], [71957, 71958, 1], [71960, 71983, 1], [71999, 72001, 2], [72096, 72103, 1], [72106, 72144, 1], [72161, 72163, 2], [72192, 72203, 11], [72204, 72242, 1], [72250, 72272, 22], [72284, 72329, 1], [72349, 72368, 19], [72369, 72440, 1], [72704, 72712, 1], [72714, 72750, 1], [72768, 72818, 50], [72819, 72847, 1], [72960, 72966, 1], [72968, 72969, 1], [72971, 73008, 1], [73030, 73056, 26], [73057, 73061, 1], [73063, 73064, 1], [73066, 73097, 1], [73112, 73440, 328], [73441, 73458, 1], [73474, 73476, 2], [73477, 73488, 1], [73490, 73523, 1], [73648, 73728, 80], [73729, 74649, 1], [74880, 75075, 1], [77712, 77808, 1], [77824, 78895, 1], [78913, 78918, 1], [82944, 83526, 1], [92160, 92728, 1], [92736, 92766, 1], [92784, 92862, 1], [92880, 92909, 1], [92928, 92975, 1], [92992, 92995, 1], [93027, 93047, 1], [93053, 93071, 1], [93760, 93823, 1], [93952, 94026, 1], [94032, 94099, 67], [94100, 94111, 1], [94176, 94177, 1], [94179, 94208, 29], [94209, 100343, 1], [100352, 101589, 1], [101632, 101640, 1], [110576, 110579, 1], [110581, 110587, 1], [110589, 110590, 1], [110592, 110882, 1], [110898, 110928, 30], [110929, 110930, 1], [110933, 110948, 15], [110949, 110951, 1], [110960, 111355, 1], [113664, 113770, 1], [113776, 113788, 1], [113792, 113800, 1], [113808, 113817, 1], [119808, 119892, 1], [119894, 119964, 1], [119966, 119967, 1], [119970, 119973, 3], [119974, 119977, 3], [119978, 119980, 1], [119982, 119993, 1], [119995, 119997, 2], [119998, 120003, 1], [120005, 120069, 1], [120071, 120074, 1], [120077, 120084, 1], [120086, 120092, 1], [120094, 120121, 1], [120123, 120126, 1], [120128, 120132, 1], [120134, 120138, 4], [120139, 120144, 1], [120146, 120485, 1], [120488, 120512, 1], [120514, 120538, 1], [120540, 120570, 1], [120572, 120596, 1], [120598, 120628, 1], [120630, 120654, 1], [120656, 120686, 1], [120688, 120712, 1], [120714, 120744, 1], [120746, 120770, 1], [120772, 120779, 1], [122624, 122654, 1], [122661, 122666, 1], [122928, 122989, 1], [123136, 123180, 1], [123191, 123197, 1], [123214, 123536, 322], [123537, 123565, 1], [123584, 123627, 1], [124112, 124139, 1], [124896, 124902, 1], [124904, 124907, 1], [124909, 124910, 1], [124912, 124926, 1], [124928, 125124, 1], [125184, 125251, 1], [125259, 126464, 1205], [126465, 126467, 1], [126469, 126495, 1], [126497, 126498, 1], [126500, 126503, 3], [126505, 126514, 1], [126516, 126519, 1], [126521, 126523, 2], [126530, 126535, 5], [126537, 126541, 2], [126542, 126543, 1], [126545, 126546, 1], [126548, 126551, 3], [126553, 126561, 2], [126562, 126564, 2], [126567, 126570, 1], [126572, 126578, 1], [126580, 126583, 1], [126585, 126588, 1], [126590, 126592, 2], [126593, 126601, 1], [126603, 126619, 1], [126625, 126627, 1], [126629, 126633, 1], [126635, 126651, 1], [131072, 173791, 1], [173824, 177977, 1], [177984, 178205, 1], [178208, 183969, 1], [183984, 191456, 1], [191472, 192093, 1], [194560, 195101, 1], [196608, 201546, 1], [201552, 205743, 1]];
    static foldL = [[837, 837, 1]];
    static Ll = [[97, 122, 1], [181, 223, 42], [224, 246, 1], [248, 255, 1], [257, 311, 2], [312, 328, 2], [329, 375, 2], [378, 382, 2], [383, 384, 1], [387, 389, 2], [392, 396, 4], [397, 402, 5], [405, 409, 4], [410, 411, 1], [414, 417, 3], [419, 421, 2], [424, 426, 2], [427, 429, 2], [432, 436, 4], [438, 441, 3], [442, 445, 3], [446, 447, 1], [454, 460, 3], [462, 476, 2], [477, 495, 2], [496, 499, 3], [501, 505, 4], [507, 563, 2], [564, 569, 1], [572, 575, 3], [576, 578, 2], [583, 591, 2], [592, 659, 1], [661, 687, 1], [881, 883, 2], [887, 891, 4], [892, 893, 1], [912, 940, 28], [941, 974, 1], [976, 977, 1], [981, 983, 1], [985, 1007, 2], [1008, 1011, 1], [1013, 1019, 3], [1020, 1072, 52], [1073, 1119, 1], [1121, 1153, 2], [1163, 1215, 2], [1218, 1230, 2], [1231, 1327, 2], [1376, 1416, 1], [4304, 4346, 1], [4349, 4351, 1], [5112, 5117, 1], [7296, 7304, 1], [7424, 7467, 1], [7531, 7543, 1], [7545, 7578, 1], [7681, 7829, 2], [7830, 7837, 1], [7839, 7935, 2], [7936, 7943, 1], [7952, 7957, 1], [7968, 7975, 1], [7984, 7991, 1], [8000, 8005, 1], [8016, 8023, 1], [8032, 8039, 1], [8048, 8061, 1], [8064, 8071, 1], [8080, 8087, 1], [8096, 8103, 1], [8112, 8116, 1], [8118, 8119, 1], [8126, 8130, 4], [8131, 8132, 1], [8134, 8135, 1], [8144, 8147, 1], [8150, 8151, 1], [8160, 8167, 1], [8178, 8180, 1], [8182, 8183, 1], [8458, 8462, 4], [8463, 8467, 4], [8495, 8505, 5], [8508, 8509, 1], [8518, 8521, 1], [8526, 8580, 54], [11312, 11359, 1], [11361, 11365, 4], [11366, 11372, 2], [11377, 11379, 2], [11380, 11382, 2], [11383, 11387, 1], [11393, 11491, 2], [11492, 11500, 8], [11502, 11507, 5], [11520, 11557, 1], [11559, 11565, 6], [42561, 42605, 2], [42625, 42651, 2], [42787, 42799, 2], [42800, 42801, 1], [42803, 42865, 2], [42866, 42872, 1], [42874, 42876, 2], [42879, 42887, 2], [42892, 42894, 2], [42897, 42899, 2], [42900, 42901, 1], [42903, 42921, 2], [42927, 42933, 6], [42935, 42947, 2], [42952, 42954, 2], [42961, 42969, 2], [42998, 43002, 4], [43824, 43866, 1], [43872, 43880, 1], [43888, 43967, 1], [64256, 64262, 1], [64275, 64279, 1], [65345, 65370, 1], [66600, 66639, 1], [66776, 66811, 1], [66967, 66977, 1], [66979, 66993, 1], [66995, 67001, 1], [67003, 67004, 1], [68800, 68850, 1], [71872, 71903, 1], [93792, 93823, 1], [119834, 119859, 1], [119886, 119892, 1], [119894, 119911, 1], [119938, 119963, 1], [119990, 119993, 1], [119995, 119997, 2], [119998, 120003, 1], [120005, 120015, 1], [120042, 120067, 1], [120094, 120119, 1], [120146, 120171, 1], [120198, 120223, 1], [120250, 120275, 1], [120302, 120327, 1], [120354, 120379, 1], [120406, 120431, 1], [120458, 120485, 1], [120514, 120538, 1], [120540, 120545, 1], [120572, 120596, 1], [120598, 120603, 1], [120630, 120654, 1], [120656, 120661, 1], [120688, 120712, 1], [120714, 120719, 1], [120746, 120770, 1], [120772, 120777, 1], [120779, 122624, 1845], [122625, 122633, 1], [122635, 122654, 1], [122661, 122666, 1], [125218, 125251, 1]];
    static foldLl = [[65, 90, 1], [192, 214, 1], [216, 222, 1], [256, 302, 2], [306, 310, 2], [313, 327, 2], [330, 376, 2], [377, 381, 2], [385, 386, 1], [388, 390, 2], [391, 393, 2], [394, 395, 1], [398, 401, 1], [403, 404, 1], [406, 408, 1], [412, 413, 1], [415, 416, 1], [418, 422, 2], [423, 425, 2], [428, 430, 2], [431, 433, 2], [434, 435, 1], [437, 439, 2], [440, 444, 4], [452, 453, 1], [455, 456, 1], [458, 459, 1], [461, 475, 2], [478, 494, 2], [497, 498, 1], [500, 502, 2], [503, 504, 1], [506, 562, 2], [570, 571, 1], [573, 574, 1], [577, 579, 2], [580, 582, 1], [584, 590, 2], [837, 880, 43], [882, 886, 4], [895, 902, 7], [904, 906, 1], [908, 910, 2], [911, 913, 2], [914, 929, 1], [931, 939, 1], [975, 984, 9], [986, 1006, 2], [1012, 1015, 3], [1017, 1018, 1], [1021, 1071, 1], [1120, 1152, 2], [1162, 1216, 2], [1217, 1229, 2], [1232, 1326, 2], [1329, 1366, 1], [4256, 4293, 1], [4295, 4301, 6], [5024, 5109, 1], [7312, 7354, 1], [7357, 7359, 1], [7680, 7828, 2], [7838, 7934, 2], [7944, 7951, 1], [7960, 7965, 1], [7976, 7983, 1], [7992, 7999, 1], [8008, 8013, 1], [8025, 8031, 2], [8040, 8047, 1], [8072, 8079, 1], [8088, 8095, 1], [8104, 8111, 1], [8120, 8124, 1], [8136, 8140, 1], [8152, 8155, 1], [8168, 8172, 1], [8184, 8188, 1], [8486, 8490, 4], [8491, 8498, 7], [8579, 11264, 2685], [11265, 11311, 1], [11360, 11362, 2], [11363, 11364, 1], [11367, 11373, 2], [11374, 11376, 1], [11378, 11381, 3], [11390, 11392, 1], [11394, 11490, 2], [11499, 11501, 2], [11506, 42560, 31054], [42562, 42604, 2], [42624, 42650, 2], [42786, 42798, 2], [42802, 42862, 2], [42873, 42877, 2], [42878, 42886, 2], [42891, 42893, 2], [42896, 42898, 2], [42902, 42922, 2], [42923, 42926, 1], [42928, 42932, 1], [42934, 42948, 2], [42949, 42951, 1], [42953, 42960, 7], [42966, 42968, 2], [42997, 65313, 22316], [65314, 65338, 1], [66560, 66599, 1], [66736, 66771, 1], [66928, 66938, 1], [66940, 66954, 1], [66956, 66962, 1], [66964, 66965, 1], [68736, 68786, 1], [71840, 71871, 1], [93760, 93791, 1], [125184, 125217, 1]];
    static Lm = [[688, 705, 1], [710, 721, 1], [736, 740, 1], [748, 750, 2], [884, 890, 6], [1369, 1600, 231], [1765, 1766, 1], [2036, 2037, 1], [2042, 2074, 32], [2084, 2088, 4], [2249, 2417, 168], [3654, 3782, 128], [4348, 6103, 1755], [6211, 6823, 612], [7288, 7293, 1], [7468, 7530, 1], [7544, 7579, 35], [7580, 7615, 1], [8305, 8319, 14], [8336, 8348, 1], [11388, 11389, 1], [11631, 11823, 192], [12293, 12337, 44], [12338, 12341, 1], [12347, 12445, 98], [12446, 12540, 94], [12541, 12542, 1], [40981, 42232, 1251], [42233, 42237, 1], [42508, 42623, 115], [42652, 42653, 1], [42775, 42783, 1], [42864, 42888, 24], [42994, 42996, 1], [43000, 43001, 1], [43471, 43494, 23], [43632, 43741, 109], [43763, 43764, 1], [43868, 43871, 1], [43881, 65392, 21511], [65438, 65439, 1], [67456, 67461, 1], [67463, 67504, 1], [67506, 67514, 1], [92992, 92995, 1], [94099, 94111, 1], [94176, 94177, 1], [94179, 110576, 16397], [110577, 110579, 1], [110581, 110587, 1], [110589, 110590, 1], [122928, 122989, 1], [123191, 123197, 1], [124139, 125259, 1120]];
    static Lo = [[170, 186, 16], [443, 448, 5], [449, 451, 1], [660, 1488, 828], [1489, 1514, 1], [1519, 1522, 1], [1568, 1599, 1], [1601, 1610, 1], [1646, 1647, 1], [1649, 1747, 1], [1749, 1774, 25], [1775, 1786, 11], [1787, 1788, 1], [1791, 1808, 17], [1810, 1839, 1], [1869, 1957, 1], [1969, 1994, 25], [1995, 2026, 1], [2048, 2069, 1], [2112, 2136, 1], [2144, 2154, 1], [2160, 2183, 1], [2185, 2190, 1], [2208, 2248, 1], [2308, 2361, 1], [2365, 2384, 19], [2392, 2401, 1], [2418, 2432, 1], [2437, 2444, 1], [2447, 2448, 1], [2451, 2472, 1], [2474, 2480, 1], [2482, 2486, 4], [2487, 2489, 1], [2493, 2510, 17], [2524, 2525, 1], [2527, 2529, 1], [2544, 2545, 1], [2556, 2565, 9], [2566, 2570, 1], [2575, 2576, 1], [2579, 2600, 1], [2602, 2608, 1], [2610, 2611, 1], [2613, 2614, 1], [2616, 2617, 1], [2649, 2652, 1], [2654, 2674, 20], [2675, 2676, 1], [2693, 2701, 1], [2703, 2705, 1], [2707, 2728, 1], [2730, 2736, 1], [2738, 2739, 1], [2741, 2745, 1], [2749, 2768, 19], [2784, 2785, 1], [2809, 2821, 12], [2822, 2828, 1], [2831, 2832, 1], [2835, 2856, 1], [2858, 2864, 1], [2866, 2867, 1], [2869, 2873, 1], [2877, 2908, 31], [2909, 2911, 2], [2912, 2913, 1], [2929, 2947, 18], [2949, 2954, 1], [2958, 2960, 1], [2962, 2965, 1], [2969, 2970, 1], [2972, 2974, 2], [2975, 2979, 4], [2980, 2984, 4], [2985, 2986, 1], [2990, 3001, 1], [3024, 3077, 53], [3078, 3084, 1], [3086, 3088, 1], [3090, 3112, 1], [3114, 3129, 1], [3133, 3160, 27], [3161, 3162, 1], [3165, 3168, 3], [3169, 3200, 31], [3205, 3212, 1], [3214, 3216, 1], [3218, 3240, 1], [3242, 3251, 1], [3253, 3257, 1], [3261, 3293, 32], [3294, 3296, 2], [3297, 3313, 16], [3314, 3332, 18], [3333, 3340, 1], [3342, 3344, 1], [3346, 3386, 1], [3389, 3406, 17], [3412, 3414, 1], [3423, 3425, 1], [3450, 3455, 1], [3461, 3478, 1], [3482, 3505, 1], [3507, 3515, 1], [3517, 3520, 3], [3521, 3526, 1], [3585, 3632, 1], [3634, 3635, 1], [3648, 3653, 1], [3713, 3714, 1], [3716, 3718, 2], [3719, 3722, 1], [3724, 3747, 1], [3749, 3751, 2], [3752, 3760, 1], [3762, 3763, 1], [3773, 3776, 3], [3777, 3780, 1], [3804, 3807, 1], [3840, 3904, 64], [3905, 3911, 1], [3913, 3948, 1], [3976, 3980, 1], [4096, 4138, 1], [4159, 4176, 17], [4177, 4181, 1], [4186, 4189, 1], [4193, 4197, 4], [4198, 4206, 8], [4207, 4208, 1], [4213, 4225, 1], [4238, 4352, 114], [4353, 4680, 1], [4682, 4685, 1], [4688, 4694, 1], [4696, 4698, 2], [4699, 4701, 1], [4704, 4744, 1], [4746, 4749, 1], [4752, 4784, 1], [4786, 4789, 1], [4792, 4798, 1], [4800, 4802, 2], [4803, 4805, 1], [4808, 4822, 1], [4824, 4880, 1], [4882, 4885, 1], [4888, 4954, 1], [4992, 5007, 1], [5121, 5740, 1], [5743, 5759, 1], [5761, 5786, 1], [5792, 5866, 1], [5873, 5880, 1], [5888, 5905, 1], [5919, 5937, 1], [5952, 5969, 1], [5984, 5996, 1], [5998, 6000, 1], [6016, 6067, 1], [6108, 6176, 68], [6177, 6210, 1], [6212, 6264, 1], [6272, 6276, 1], [6279, 6312, 1], [6314, 6320, 6], [6321, 6389, 1], [6400, 6430, 1], [6480, 6509, 1], [6512, 6516, 1], [6528, 6571, 1], [6576, 6601, 1], [6656, 6678, 1], [6688, 6740, 1], [6917, 6963, 1], [6981, 6988, 1], [7043, 7072, 1], [7086, 7087, 1], [7098, 7141, 1], [7168, 7203, 1], [7245, 7247, 1], [7258, 7287, 1], [7401, 7404, 1], [7406, 7411, 1], [7413, 7414, 1], [7418, 8501, 1083], [8502, 8504, 1], [11568, 11623, 1], [11648, 11670, 1], [11680, 11686, 1], [11688, 11694, 1], [11696, 11702, 1], [11704, 11710, 1], [11712, 11718, 1], [11720, 11726, 1], [11728, 11734, 1], [11736, 11742, 1], [12294, 12348, 54], [12353, 12438, 1], [12447, 12449, 2], [12450, 12538, 1], [12543, 12549, 6], [12550, 12591, 1], [12593, 12686, 1], [12704, 12735, 1], [12784, 12799, 1], [13312, 19903, 1], [19968, 40980, 1], [40982, 42124, 1], [42192, 42231, 1], [42240, 42507, 1], [42512, 42527, 1], [42538, 42539, 1], [42606, 42656, 50], [42657, 42725, 1], [42895, 42999, 104], [43003, 43009, 1], [43011, 43013, 1], [43015, 43018, 1], [43020, 43042, 1], [43072, 43123, 1], [43138, 43187, 1], [43250, 43255, 1], [43259, 43261, 2], [43262, 43274, 12], [43275, 43301, 1], [43312, 43334, 1], [43360, 43388, 1], [43396, 43442, 1], [43488, 43492, 1], [43495, 43503, 1], [43514, 43518, 1], [43520, 43560, 1], [43584, 43586, 1], [43588, 43595, 1], [43616, 43631, 1], [43633, 43638, 1], [43642, 43646, 4], [43647, 43695, 1], [43697, 43701, 4], [43702, 43705, 3], [43706, 43709, 1], [43712, 43714, 2], [43739, 43740, 1], [43744, 43754, 1], [43762, 43777, 15], [43778, 43782, 1], [43785, 43790, 1], [43793, 43798, 1], [43808, 43814, 1], [43816, 43822, 1], [43968, 44002, 1], [44032, 55203, 1], [55216, 55238, 1], [55243, 55291, 1], [63744, 64109, 1], [64112, 64217, 1], [64285, 64287, 2], [64288, 64296, 1], [64298, 64310, 1], [64312, 64316, 1], [64318, 64320, 2], [64321, 64323, 2], [64324, 64326, 2], [64327, 64433, 1], [64467, 64829, 1], [64848, 64911, 1], [64914, 64967, 1], [65008, 65019, 1], [65136, 65140, 1], [65142, 65276, 1], [65382, 65391, 1], [65393, 65437, 1], [65440, 65470, 1], [65474, 65479, 1], [65482, 65487, 1], [65490, 65495, 1], [65498, 65500, 1], [65536, 65547, 1], [65549, 65574, 1], [65576, 65594, 1], [65596, 65597, 1], [65599, 65613, 1], [65616, 65629, 1], [65664, 65786, 1], [66176, 66204, 1], [66208, 66256, 1], [66304, 66335, 1], [66349, 66368, 1], [66370, 66377, 1], [66384, 66421, 1], [66432, 66461, 1], [66464, 66499, 1], [66504, 66511, 1], [66640, 66717, 1], [66816, 66855, 1], [66864, 66915, 1], [67072, 67382, 1], [67392, 67413, 1], [67424, 67431, 1], [67584, 67589, 1], [67592, 67594, 2], [67595, 67637, 1], [67639, 67640, 1], [67644, 67647, 3], [67648, 67669, 1], [67680, 67702, 1], [67712, 67742, 1], [67808, 67826, 1], [67828, 67829, 1], [67840, 67861, 1], [67872, 67897, 1], [67968, 68023, 1], [68030, 68031, 1], [68096, 68112, 16], [68113, 68115, 1], [68117, 68119, 1], [68121, 68149, 1], [68192, 68220, 1], [68224, 68252, 1], [68288, 68295, 1], [68297, 68324, 1], [68352, 68405, 1], [68416, 68437, 1], [68448, 68466, 1], [68480, 68497, 1], [68608, 68680, 1], [68864, 68899, 1], [69248, 69289, 1], [69296, 69297, 1], [69376, 69404, 1], [69415, 69424, 9], [69425, 69445, 1], [69488, 69505, 1], [69552, 69572, 1], [69600, 69622, 1], [69635, 69687, 1], [69745, 69746, 1], [69749, 69763, 14], [69764, 69807, 1], [69840, 69864, 1], [69891, 69926, 1], [69956, 69959, 3], [69968, 70002, 1], [70006, 70019, 13], [70020, 70066, 1], [70081, 70084, 1], [70106, 70108, 2], [70144, 70161, 1], [70163, 70187, 1], [70207, 70208, 1], [70272, 70278, 1], [70280, 70282, 2], [70283, 70285, 1], [70287, 70301, 1], [70303, 70312, 1], [70320, 70366, 1], [70405, 70412, 1], [70415, 70416, 1], [70419, 70440, 1], [70442, 70448, 1], [70450, 70451, 1], [70453, 70457, 1], [70461, 70480, 19], [70493, 70497, 1], [70656, 70708, 1], [70727, 70730, 1], [70751, 70753, 1], [70784, 70831, 1], [70852, 70853, 1], [70855, 71040, 185], [71041, 71086, 1], [71128, 71131, 1], [71168, 71215, 1], [71236, 71296, 60], [71297, 71338, 1], [71352, 71424, 72], [71425, 71450, 1], [71488, 71494, 1], [71680, 71723, 1], [71935, 71942, 1], [71945, 71948, 3], [71949, 71955, 1], [71957, 71958, 1], [71960, 71983, 1], [71999, 72001, 2], [72096, 72103, 1], [72106, 72144, 1], [72161, 72163, 2], [72192, 72203, 11], [72204, 72242, 1], [72250, 72272, 22], [72284, 72329, 1], [72349, 72368, 19], [72369, 72440, 1], [72704, 72712, 1], [72714, 72750, 1], [72768, 72818, 50], [72819, 72847, 1], [72960, 72966, 1], [72968, 72969, 1], [72971, 73008, 1], [73030, 73056, 26], [73057, 73061, 1], [73063, 73064, 1], [73066, 73097, 1], [73112, 73440, 328], [73441, 73458, 1], [73474, 73476, 2], [73477, 73488, 1], [73490, 73523, 1], [73648, 73728, 80], [73729, 74649, 1], [74880, 75075, 1], [77712, 77808, 1], [77824, 78895, 1], [78913, 78918, 1], [82944, 83526, 1], [92160, 92728, 1], [92736, 92766, 1], [92784, 92862, 1], [92880, 92909, 1], [92928, 92975, 1], [93027, 93047, 1], [93053, 93071, 1], [93952, 94026, 1], [94032, 94208, 176], [94209, 100343, 1], [100352, 101589, 1], [101632, 101640, 1], [110592, 110882, 1], [110898, 110928, 30], [110929, 110930, 1], [110933, 110948, 15], [110949, 110951, 1], [110960, 111355, 1], [113664, 113770, 1], [113776, 113788, 1], [113792, 113800, 1], [113808, 113817, 1], [122634, 123136, 502], [123137, 123180, 1], [123214, 123536, 322], [123537, 123565, 1], [123584, 123627, 1], [124112, 124138, 1], [124896, 124902, 1], [124904, 124907, 1], [124909, 124910, 1], [124912, 124926, 1], [124928, 125124, 1], [126464, 126467, 1], [126469, 126495, 1], [126497, 126498, 1], [126500, 126503, 3], [126505, 126514, 1], [126516, 126519, 1], [126521, 126523, 2], [126530, 126535, 5], [126537, 126541, 2], [126542, 126543, 1], [126545, 126546, 1], [126548, 126551, 3], [126553, 126561, 2], [126562, 126564, 2], [126567, 126570, 1], [126572, 126578, 1], [126580, 126583, 1], [126585, 126588, 1], [126590, 126592, 2], [126593, 126601, 1], [126603, 126619, 1], [126625, 126627, 1], [126629, 126633, 1], [126635, 126651, 1], [131072, 173791, 1], [173824, 177977, 1], [177984, 178205, 1], [178208, 183969, 1], [183984, 191456, 1], [191472, 192093, 1], [194560, 195101, 1], [196608, 201546, 1], [201552, 205743, 1]];
    static Lt = [[453, 459, 3], [498, 8072, 7574], [8073, 8079, 1], [8088, 8095, 1], [8104, 8111, 1], [8124, 8140, 16], [8188, 8188, 1]];
    static foldLt = [[452, 454, 2], [455, 457, 2], [458, 460, 2], [497, 499, 2], [8064, 8071, 1], [8080, 8087, 1], [8096, 8103, 1], [8115, 8131, 16], [8179, 8179, 1]];
    static Lu = [[65, 90, 1], [192, 214, 1], [216, 222, 1], [256, 310, 2], [313, 327, 2], [330, 376, 2], [377, 381, 2], [385, 386, 1], [388, 390, 2], [391, 393, 2], [394, 395, 1], [398, 401, 1], [403, 404, 1], [406, 408, 1], [412, 413, 1], [415, 416, 1], [418, 422, 2], [423, 425, 2], [428, 430, 2], [431, 433, 2], [434, 435, 1], [437, 439, 2], [440, 444, 4], [452, 461, 3], [463, 475, 2], [478, 494, 2], [497, 500, 3], [502, 504, 1], [506, 562, 2], [570, 571, 1], [573, 574, 1], [577, 579, 2], [580, 582, 1], [584, 590, 2], [880, 882, 2], [886, 895, 9], [902, 904, 2], [905, 906, 1], [908, 910, 2], [911, 913, 2], [914, 929, 1], [931, 939, 1], [975, 978, 3], [979, 980, 1], [984, 1006, 2], [1012, 1015, 3], [1017, 1018, 1], [1021, 1071, 1], [1120, 1152, 2], [1162, 1216, 2], [1217, 1229, 2], [1232, 1326, 2], [1329, 1366, 1], [4256, 4293, 1], [4295, 4301, 6], [5024, 5109, 1], [7312, 7354, 1], [7357, 7359, 1], [7680, 7828, 2], [7838, 7934, 2], [7944, 7951, 1], [7960, 7965, 1], [7976, 7983, 1], [7992, 7999, 1], [8008, 8013, 1], [8025, 8031, 2], [8040, 8047, 1], [8120, 8123, 1], [8136, 8139, 1], [8152, 8155, 1], [8168, 8172, 1], [8184, 8187, 1], [8450, 8455, 5], [8459, 8461, 1], [8464, 8466, 1], [8469, 8473, 4], [8474, 8477, 1], [8484, 8490, 2], [8491, 8493, 1], [8496, 8499, 1], [8510, 8511, 1], [8517, 8579, 62], [11264, 11311, 1], [11360, 11362, 2], [11363, 11364, 1], [11367, 11373, 2], [11374, 11376, 1], [11378, 11381, 3], [11390, 11392, 1], [11394, 11490, 2], [11499, 11501, 2], [11506, 42560, 31054], [42562, 42604, 2], [42624, 42650, 2], [42786, 42798, 2], [42802, 42862, 2], [42873, 42877, 2], [42878, 42886, 2], [42891, 42893, 2], [42896, 42898, 2], [42902, 42922, 2], [42923, 42926, 1], [42928, 42932, 1], [42934, 42948, 2], [42949, 42951, 1], [42953, 42960, 7], [42966, 42968, 2], [42997, 65313, 22316], [65314, 65338, 1], [66560, 66599, 1], [66736, 66771, 1], [66928, 66938, 1], [66940, 66954, 1], [66956, 66962, 1], [66964, 66965, 1], [68736, 68786, 1], [71840, 71871, 1], [93760, 93791, 1], [119808, 119833, 1], [119860, 119885, 1], [119912, 119937, 1], [119964, 119966, 2], [119967, 119973, 3], [119974, 119977, 3], [119978, 119980, 1], [119982, 119989, 1], [120016, 120041, 1], [120068, 120069, 1], [120071, 120074, 1], [120077, 120084, 1], [120086, 120092, 1], [120120, 120121, 1], [120123, 120126, 1], [120128, 120132, 1], [120134, 120138, 4], [120139, 120144, 1], [120172, 120197, 1], [120224, 120249, 1], [120276, 120301, 1], [120328, 120353, 1], [120380, 120405, 1], [120432, 120457, 1], [120488, 120512, 1], [120546, 120570, 1], [120604, 120628, 1], [120662, 120686, 1], [120720, 120744, 1], [120778, 125184, 4406], [125185, 125217, 1]];
    static Upper = this.Lu;
    static foldLu = [[97, 122, 1], [181, 223, 42], [224, 246, 1], [248, 255, 1], [257, 303, 2], [307, 311, 2], [314, 328, 2], [331, 375, 2], [378, 382, 2], [383, 384, 1], [387, 389, 2], [392, 396, 4], [402, 405, 3], [409, 410, 1], [414, 417, 3], [419, 421, 2], [424, 429, 5], [432, 436, 4], [438, 441, 3], [445, 447, 2], [453, 454, 1], [456, 457, 1], [459, 460, 1], [462, 476, 2], [477, 495, 2], [498, 499, 1], [501, 505, 4], [507, 543, 2], [547, 563, 2], [572, 575, 3], [576, 578, 2], [583, 591, 2], [592, 596, 1], [598, 599, 1], [601, 603, 2], [604, 608, 4], [609, 613, 2], [614, 616, 2], [617, 620, 1], [623, 625, 2], [626, 629, 3], [637, 640, 3], [642, 643, 1], [647, 652, 1], [658, 669, 11], [670, 837, 167], [881, 883, 2], [887, 891, 4], [892, 893, 1], [940, 943, 1], [945, 974, 1], [976, 977, 1], [981, 983, 1], [985, 1007, 2], [1008, 1011, 1], [1013, 1019, 3], [1072, 1119, 1], [1121, 1153, 2], [1163, 1215, 2], [1218, 1230, 2], [1231, 1327, 2], [1377, 1414, 1], [4304, 4346, 1], [4349, 4351, 1], [5112, 5117, 1], [7296, 7304, 1], [7545, 7549, 4], [7566, 7681, 115], [7683, 7829, 2], [7835, 7841, 6], [7843, 7935, 2], [7936, 7943, 1], [7952, 7957, 1], [7968, 7975, 1], [7984, 7991, 1], [8000, 8005, 1], [8017, 8023, 2], [8032, 8039, 1], [8048, 8061, 1], [8112, 8113, 1], [8126, 8144, 18], [8145, 8160, 15], [8161, 8165, 4], [8526, 8580, 54], [11312, 11359, 1], [11361, 11365, 4], [11366, 11372, 2], [11379, 11382, 3], [11393, 11491, 2], [11500, 11502, 2], [11507, 11520, 13], [11521, 11557, 1], [11559, 11565, 6], [42561, 42605, 2], [42625, 42651, 2], [42787, 42799, 2], [42803, 42863, 2], [42874, 42876, 2], [42879, 42887, 2], [42892, 42897, 5], [42899, 42900, 1], [42903, 42921, 2], [42933, 42947, 2], [42952, 42954, 2], [42961, 42967, 6], [42969, 42998, 29], [43859, 43888, 29], [43889, 43967, 1], [65345, 65370, 1], [66600, 66639, 1], [66776, 66811, 1], [66967, 66977, 1], [66979, 66993, 1], [66995, 67001, 1], [67003, 67004, 1], [68800, 68850, 1], [71872, 71903, 1], [93792, 93823, 1], [125218, 125251, 1]];
    static M = [[768, 879, 1], [1155, 1161, 1], [1425, 1469, 1], [1471, 1473, 2], [1474, 1476, 2], [1477, 1479, 2], [1552, 1562, 1], [1611, 1631, 1], [1648, 1750, 102], [1751, 1756, 1], [1759, 1764, 1], [1767, 1768, 1], [1770, 1773, 1], [1809, 1840, 31], [1841, 1866, 1], [1958, 1968, 1], [2027, 2035, 1], [2045, 2070, 25], [2071, 2073, 1], [2075, 2083, 1], [2085, 2087, 1], [2089, 2093, 1], [2137, 2139, 1], [2200, 2207, 1], [2250, 2273, 1], [2275, 2307, 1], [2362, 2364, 1], [2366, 2383, 1], [2385, 2391, 1], [2402, 2403, 1], [2433, 2435, 1], [2492, 2494, 2], [2495, 2500, 1], [2503, 2504, 1], [2507, 2509, 1], [2519, 2530, 11], [2531, 2558, 27], [2561, 2563, 1], [2620, 2622, 2], [2623, 2626, 1], [2631, 2632, 1], [2635, 2637, 1], [2641, 2672, 31], [2673, 2677, 4], [2689, 2691, 1], [2748, 2750, 2], [2751, 2757, 1], [2759, 2761, 1], [2763, 2765, 1], [2786, 2787, 1], [2810, 2815, 1], [2817, 2819, 1], [2876, 2878, 2], [2879, 2884, 1], [2887, 2888, 1], [2891, 2893, 1], [2901, 2903, 1], [2914, 2915, 1], [2946, 3006, 60], [3007, 3010, 1], [3014, 3016, 1], [3018, 3021, 1], [3031, 3072, 41], [3073, 3076, 1], [3132, 3134, 2], [3135, 3140, 1], [3142, 3144, 1], [3146, 3149, 1], [3157, 3158, 1], [3170, 3171, 1], [3201, 3203, 1], [3260, 3262, 2], [3263, 3268, 1], [3270, 3272, 1], [3274, 3277, 1], [3285, 3286, 1], [3298, 3299, 1], [3315, 3328, 13], [3329, 3331, 1], [3387, 3388, 1], [3390, 3396, 1], [3398, 3400, 1], [3402, 3405, 1], [3415, 3426, 11], [3427, 3457, 30], [3458, 3459, 1], [3530, 3535, 5], [3536, 3540, 1], [3542, 3544, 2], [3545, 3551, 1], [3570, 3571, 1], [3633, 3636, 3], [3637, 3642, 1], [3655, 3662, 1], [3761, 3764, 3], [3765, 3772, 1], [3784, 3790, 1], [3864, 3865, 1], [3893, 3897, 2], [3902, 3903, 1], [3953, 3972, 1], [3974, 3975, 1], [3981, 3991, 1], [3993, 4028, 1], [4038, 4139, 101], [4140, 4158, 1], [4182, 4185, 1], [4190, 4192, 1], [4194, 4196, 1], [4199, 4205, 1], [4209, 4212, 1], [4226, 4237, 1], [4239, 4250, 11], [4251, 4253, 1], [4957, 4959, 1], [5906, 5909, 1], [5938, 5940, 1], [5970, 5971, 1], [6002, 6003, 1], [6068, 6099, 1], [6109, 6155, 46], [6156, 6157, 1], [6159, 6277, 118], [6278, 6313, 35], [6432, 6443, 1], [6448, 6459, 1], [6679, 6683, 1], [6741, 6750, 1], [6752, 6780, 1], [6783, 6832, 49], [6833, 6862, 1], [6912, 6916, 1], [6964, 6980, 1], [7019, 7027, 1], [7040, 7042, 1], [7073, 7085, 1], [7142, 7155, 1], [7204, 7223, 1], [7376, 7378, 1], [7380, 7400, 1], [7405, 7412, 7], [7415, 7417, 1], [7616, 7679, 1], [8400, 8432, 1], [11503, 11505, 1], [11647, 11744, 97], [11745, 11775, 1], [12330, 12335, 1], [12441, 12442, 1], [42607, 42610, 1], [42612, 42621, 1], [42654, 42655, 1], [42736, 42737, 1], [43010, 43014, 4], [43019, 43043, 24], [43044, 43047, 1], [43052, 43136, 84], [43137, 43188, 51], [43189, 43205, 1], [43232, 43249, 1], [43263, 43302, 39], [43303, 43309, 1], [43335, 43347, 1], [43392, 43395, 1], [43443, 43456, 1], [43493, 43561, 68], [43562, 43574, 1], [43587, 43596, 9], [43597, 43643, 46], [43644, 43645, 1], [43696, 43698, 2], [43699, 43700, 1], [43703, 43704, 1], [43710, 43711, 1], [43713, 43755, 42], [43756, 43759, 1], [43765, 43766, 1], [44003, 44010, 1], [44012, 44013, 1], [64286, 65024, 738], [65025, 65039, 1], [65056, 65071, 1], [66045, 66272, 227], [66422, 66426, 1], [68097, 68099, 1], [68101, 68102, 1], [68108, 68111, 1], [68152, 68154, 1], [68159, 68325, 166], [68326, 68900, 574], [68901, 68903, 1], [69291, 69292, 1], [69373, 69375, 1], [69446, 69456, 1], [69506, 69509, 1], [69632, 69634, 1], [69688, 69702, 1], [69744, 69747, 3], [69748, 69759, 11], [69760, 69762, 1], [69808, 69818, 1], [69826, 69888, 62], [69889, 69890, 1], [69927, 69940, 1], [69957, 69958, 1], [70003, 70016, 13], [70017, 70018, 1], [70067, 70080, 1], [70089, 70092, 1], [70094, 70095, 1], [70188, 70199, 1], [70206, 70209, 3], [70367, 70378, 1], [70400, 70403, 1], [70459, 70460, 1], [70462, 70468, 1], [70471, 70472, 1], [70475, 70477, 1], [70487, 70498, 11], [70499, 70502, 3], [70503, 70508, 1], [70512, 70516, 1], [70709, 70726, 1], [70750, 70832, 82], [70833, 70851, 1], [71087, 71093, 1], [71096, 71104, 1], [71132, 71133, 1], [71216, 71232, 1], [71339, 71351, 1], [71453, 71467, 1], [71724, 71738, 1], [71984, 71989, 1], [71991, 71992, 1], [71995, 71998, 1], [72000, 72002, 2], [72003, 72145, 142], [72146, 72151, 1], [72154, 72160, 1], [72164, 72193, 29], [72194, 72202, 1], [72243, 72249, 1], [72251, 72254, 1], [72263, 72273, 10], [72274, 72283, 1], [72330, 72345, 1], [72751, 72758, 1], [72760, 72767, 1], [72850, 72871, 1], [72873, 72886, 1], [73009, 73014, 1], [73018, 73020, 2], [73021, 73023, 2], [73024, 73029, 1], [73031, 73098, 67], [73099, 73102, 1], [73104, 73105, 1], [73107, 73111, 1], [73459, 73462, 1], [73472, 73473, 1], [73475, 73524, 49], [73525, 73530, 1], [73534, 73538, 1], [78912, 78919, 7], [78920, 78933, 1], [92912, 92916, 1], [92976, 92982, 1], [94031, 94033, 2], [94034, 94087, 1], [94095, 94098, 1], [94180, 94192, 12], [94193, 113821, 19628], [113822, 118528, 4706], [118529, 118573, 1], [118576, 118598, 1], [119141, 119145, 1], [119149, 119154, 1], [119163, 119170, 1], [119173, 119179, 1], [119210, 119213, 1], [119362, 119364, 1], [121344, 121398, 1], [121403, 121452, 1], [121461, 121476, 15], [121499, 121503, 1], [121505, 121519, 1], [122880, 122886, 1], [122888, 122904, 1], [122907, 122913, 1], [122915, 122916, 1], [122918, 122922, 1], [123023, 123184, 161], [123185, 123190, 1], [123566, 123628, 62], [123629, 123631, 1], [124140, 124143, 1], [125136, 125142, 1], [125252, 125258, 1], [917760, 917999, 1]];
    static foldM = [[921, 953, 32], [8126, 8126, 1]];
    static Mc = [[2307, 2363, 56], [2366, 2368, 1], [2377, 2380, 1], [2382, 2383, 1], [2434, 2435, 1], [2494, 2496, 1], [2503, 2504, 1], [2507, 2508, 1], [2519, 2563, 44], [2622, 2624, 1], [2691, 2750, 59], [2751, 2752, 1], [2761, 2763, 2], [2764, 2818, 54], [2819, 2878, 59], [2880, 2887, 7], [2888, 2891, 3], [2892, 2903, 11], [3006, 3007, 1], [3009, 3010, 1], [3014, 3016, 1], [3018, 3020, 1], [3031, 3073, 42], [3074, 3075, 1], [3137, 3140, 1], [3202, 3203, 1], [3262, 3264, 2], [3265, 3268, 1], [3271, 3272, 1], [3274, 3275, 1], [3285, 3286, 1], [3315, 3330, 15], [3331, 3390, 59], [3391, 3392, 1], [3398, 3400, 1], [3402, 3404, 1], [3415, 3458, 43], [3459, 3535, 76], [3536, 3537, 1], [3544, 3551, 1], [3570, 3571, 1], [3902, 3903, 1], [3967, 4139, 172], [4140, 4145, 5], [4152, 4155, 3], [4156, 4182, 26], [4183, 4194, 11], [4195, 4196, 1], [4199, 4205, 1], [4227, 4228, 1], [4231, 4236, 1], [4239, 4250, 11], [4251, 4252, 1], [5909, 5940, 31], [6070, 6078, 8], [6079, 6085, 1], [6087, 6088, 1], [6435, 6438, 1], [6441, 6443, 1], [6448, 6449, 1], [6451, 6456, 1], [6681, 6682, 1], [6741, 6743, 2], [6753, 6755, 2], [6756, 6765, 9], [6766, 6770, 1], [6916, 6965, 49], [6971, 6973, 2], [6974, 6977, 1], [6979, 6980, 1], [7042, 7073, 31], [7078, 7079, 1], [7082, 7143, 61], [7146, 7148, 1], [7150, 7154, 4], [7155, 7204, 49], [7205, 7211, 1], [7220, 7221, 1], [7393, 7415, 22], [12334, 12335, 1], [43043, 43044, 1], [43047, 43136, 89], [43137, 43188, 51], [43189, 43203, 1], [43346, 43347, 1], [43395, 43444, 49], [43445, 43450, 5], [43451, 43454, 3], [43455, 43456, 1], [43567, 43568, 1], [43571, 43572, 1], [43597, 43643, 46], [43645, 43755, 110], [43758, 43759, 1], [43765, 44003, 238], [44004, 44006, 2], [44007, 44009, 2], [44010, 44012, 2], [69632, 69634, 2], [69762, 69808, 46], [69809, 69810, 1], [69815, 69816, 1], [69932, 69957, 25], [69958, 70018, 60], [70067, 70069, 1], [70079, 70080, 1], [70094, 70188, 94], [70189, 70190, 1], [70194, 70195, 1], [70197, 70368, 171], [70369, 70370, 1], [70402, 70403, 1], [70462, 70463, 1], [70465, 70468, 1], [70471, 70472, 1], [70475, 70477, 1], [70487, 70498, 11], [70499, 70709, 210], [70710, 70711, 1], [70720, 70721, 1], [70725, 70832, 107], [70833, 70834, 1], [70841, 70843, 2], [70844, 70846, 1], [70849, 71087, 238], [71088, 71089, 1], [71096, 71099, 1], [71102, 71216, 114], [71217, 71218, 1], [71227, 71228, 1], [71230, 71340, 110], [71342, 71343, 1], [71350, 71456, 106], [71457, 71462, 5], [71724, 71726, 1], [71736, 71984, 248], [71985, 71989, 1], [71991, 71992, 1], [71997, 72000, 3], [72002, 72145, 143], [72146, 72147, 1], [72156, 72159, 1], [72164, 72249, 85], [72279, 72280, 1], [72343, 72751, 408], [72766, 72873, 107], [72881, 72884, 3], [73098, 73102, 1], [73107, 73108, 1], [73110, 73461, 351], [73462, 73475, 13], [73524, 73525, 1], [73534, 73535, 1], [73537, 94033, 20496], [94034, 94087, 1], [94192, 94193, 1], [119141, 119142, 1], [119149, 119154, 1]];
    static Me = [[1160, 1161, 1], [6846, 8413, 1567], [8414, 8416, 1], [8418, 8420, 1], [42608, 42610, 1]];
    static Mn = [[768, 879, 1], [1155, 1159, 1], [1425, 1469, 1], [1471, 1473, 2], [1474, 1476, 2], [1477, 1479, 2], [1552, 1562, 1], [1611, 1631, 1], [1648, 1750, 102], [1751, 1756, 1], [1759, 1764, 1], [1767, 1768, 1], [1770, 1773, 1], [1809, 1840, 31], [1841, 1866, 1], [1958, 1968, 1], [2027, 2035, 1], [2045, 2070, 25], [2071, 2073, 1], [2075, 2083, 1], [2085, 2087, 1], [2089, 2093, 1], [2137, 2139, 1], [2200, 2207, 1], [2250, 2273, 1], [2275, 2306, 1], [2362, 2364, 2], [2369, 2376, 1], [2381, 2385, 4], [2386, 2391, 1], [2402, 2403, 1], [2433, 2492, 59], [2497, 2500, 1], [2509, 2530, 21], [2531, 2558, 27], [2561, 2562, 1], [2620, 2625, 5], [2626, 2631, 5], [2632, 2635, 3], [2636, 2637, 1], [2641, 2672, 31], [2673, 2677, 4], [2689, 2690, 1], [2748, 2753, 5], [2754, 2757, 1], [2759, 2760, 1], [2765, 2786, 21], [2787, 2810, 23], [2811, 2815, 1], [2817, 2876, 59], [2879, 2881, 2], [2882, 2884, 1], [2893, 2901, 8], [2902, 2914, 12], [2915, 2946, 31], [3008, 3021, 13], [3072, 3076, 4], [3132, 3134, 2], [3135, 3136, 1], [3142, 3144, 1], [3146, 3149, 1], [3157, 3158, 1], [3170, 3171, 1], [3201, 3260, 59], [3263, 3270, 7], [3276, 3277, 1], [3298, 3299, 1], [3328, 3329, 1], [3387, 3388, 1], [3393, 3396, 1], [3405, 3426, 21], [3427, 3457, 30], [3530, 3538, 8], [3539, 3540, 1], [3542, 3633, 91], [3636, 3642, 1], [3655, 3662, 1], [3761, 3764, 3], [3765, 3772, 1], [3784, 3790, 1], [3864, 3865, 1], [3893, 3897, 2], [3953, 3966, 1], [3968, 3972, 1], [3974, 3975, 1], [3981, 3991, 1], [3993, 4028, 1], [4038, 4141, 103], [4142, 4144, 1], [4146, 4151, 1], [4153, 4154, 1], [4157, 4158, 1], [4184, 4185, 1], [4190, 4192, 1], [4209, 4212, 1], [4226, 4229, 3], [4230, 4237, 7], [4253, 4957, 704], [4958, 4959, 1], [5906, 5908, 1], [5938, 5939, 1], [5970, 5971, 1], [6002, 6003, 1], [6068, 6069, 1], [6071, 6077, 1], [6086, 6089, 3], [6090, 6099, 1], [6109, 6155, 46], [6156, 6157, 1], [6159, 6277, 118], [6278, 6313, 35], [6432, 6434, 1], [6439, 6440, 1], [6450, 6457, 7], [6458, 6459, 1], [6679, 6680, 1], [6683, 6742, 59], [6744, 6750, 1], [6752, 6754, 2], [6757, 6764, 1], [6771, 6780, 1], [6783, 6832, 49], [6833, 6845, 1], [6847, 6862, 1], [6912, 6915, 1], [6964, 6966, 2], [6967, 6970, 1], [6972, 6978, 6], [7019, 7027, 1], [7040, 7041, 1], [7074, 7077, 1], [7080, 7081, 1], [7083, 7085, 1], [7142, 7144, 2], [7145, 7149, 4], [7151, 7153, 1], [7212, 7219, 1], [7222, 7223, 1], [7376, 7378, 1], [7380, 7392, 1], [7394, 7400, 1], [7405, 7412, 7], [7416, 7417, 1], [7616, 7679, 1], [8400, 8412, 1], [8417, 8421, 4], [8422, 8432, 1], [11503, 11505, 1], [11647, 11744, 97], [11745, 11775, 1], [12330, 12333, 1], [12441, 12442, 1], [42607, 42612, 5], [42613, 42621, 1], [42654, 42655, 1], [42736, 42737, 1], [43010, 43014, 4], [43019, 43045, 26], [43046, 43052, 6], [43204, 43205, 1], [43232, 43249, 1], [43263, 43302, 39], [43303, 43309, 1], [43335, 43345, 1], [43392, 43394, 1], [43443, 43446, 3], [43447, 43449, 1], [43452, 43453, 1], [43493, 43561, 68], [43562, 43566, 1], [43569, 43570, 1], [43573, 43574, 1], [43587, 43596, 9], [43644, 43696, 52], [43698, 43700, 1], [43703, 43704, 1], [43710, 43711, 1], [43713, 43756, 43], [43757, 43766, 9], [44005, 44008, 3], [44013, 64286, 20273], [65024, 65039, 1], [65056, 65071, 1], [66045, 66272, 227], [66422, 66426, 1], [68097, 68099, 1], [68101, 68102, 1], [68108, 68111, 1], [68152, 68154, 1], [68159, 68325, 166], [68326, 68900, 574], [68901, 68903, 1], [69291, 69292, 1], [69373, 69375, 1], [69446, 69456, 1], [69506, 69509, 1], [69633, 69688, 55], [69689, 69702, 1], [69744, 69747, 3], [69748, 69759, 11], [69760, 69761, 1], [69811, 69814, 1], [69817, 69818, 1], [69826, 69888, 62], [69889, 69890, 1], [69927, 69931, 1], [69933, 69940, 1], [70003, 70016, 13], [70017, 70070, 53], [70071, 70078, 1], [70089, 70092, 1], [70095, 70191, 96], [70192, 70193, 1], [70196, 70198, 2], [70199, 70206, 7], [70209, 70367, 158], [70371, 70378, 1], [70400, 70401, 1], [70459, 70460, 1], [70464, 70502, 38], [70503, 70508, 1], [70512, 70516, 1], [70712, 70719, 1], [70722, 70724, 1], [70726, 70750, 24], [70835, 70840, 1], [70842, 70847, 5], [70848, 70850, 2], [70851, 71090, 239], [71091, 71093, 1], [71100, 71101, 1], [71103, 71104, 1], [71132, 71133, 1], [71219, 71226, 1], [71229, 71231, 2], [71232, 71339, 107], [71341, 71344, 3], [71345, 71349, 1], [71351, 71453, 102], [71454, 71455, 1], [71458, 71461, 1], [71463, 71467, 1], [71727, 71735, 1], [71737, 71738, 1], [71995, 71996, 1], [71998, 72003, 5], [72148, 72151, 1], [72154, 72155, 1], [72160, 72193, 33], [72194, 72202, 1], [72243, 72248, 1], [72251, 72254, 1], [72263, 72273, 10], [72274, 72278, 1], [72281, 72283, 1], [72330, 72342, 1], [72344, 72345, 1], [72752, 72758, 1], [72760, 72765, 1], [72767, 72850, 83], [72851, 72871, 1], [72874, 72880, 1], [72882, 72883, 1], [72885, 72886, 1], [73009, 73014, 1], [73018, 73020, 2], [73021, 73023, 2], [73024, 73029, 1], [73031, 73104, 73], [73105, 73109, 4], [73111, 73459, 348], [73460, 73472, 12], [73473, 73526, 53], [73527, 73530, 1], [73536, 73538, 2], [78912, 78919, 7], [78920, 78933, 1], [92912, 92916, 1], [92976, 92982, 1], [94031, 94095, 64], [94096, 94098, 1], [94180, 113821, 19641], [113822, 118528, 4706], [118529, 118573, 1], [118576, 118598, 1], [119143, 119145, 1], [119163, 119170, 1], [119173, 119179, 1], [119210, 119213, 1], [119362, 119364, 1], [121344, 121398, 1], [121403, 121452, 1], [121461, 121476, 15], [121499, 121503, 1], [121505, 121519, 1], [122880, 122886, 1], [122888, 122904, 1], [122907, 122913, 1], [122915, 122916, 1], [122918, 122922, 1], [123023, 123184, 161], [123185, 123190, 1], [123566, 123628, 62], [123629, 123631, 1], [124140, 124143, 1], [125136, 125142, 1], [125252, 125258, 1], [917760, 917999, 1]];
    static foldMn = [[921, 953, 32], [8126, 8126, 1]];
    static N = [[48, 57, 1], [178, 179, 1], [185, 188, 3], [189, 190, 1], [1632, 1641, 1], [1776, 1785, 1], [1984, 1993, 1], [2406, 2415, 1], [2534, 2543, 1], [2548, 2553, 1], [2662, 2671, 1], [2790, 2799, 1], [2918, 2927, 1], [2930, 2935, 1], [3046, 3058, 1], [3174, 3183, 1], [3192, 3198, 1], [3302, 3311, 1], [3416, 3422, 1], [3430, 3448, 1], [3558, 3567, 1], [3664, 3673, 1], [3792, 3801, 1], [3872, 3891, 1], [4160, 4169, 1], [4240, 4249, 1], [4969, 4988, 1], [5870, 5872, 1], [6112, 6121, 1], [6128, 6137, 1], [6160, 6169, 1], [6470, 6479, 1], [6608, 6618, 1], [6784, 6793, 1], [6800, 6809, 1], [6992, 7001, 1], [7088, 7097, 1], [7232, 7241, 1], [7248, 7257, 1], [8304, 8308, 4], [8309, 8313, 1], [8320, 8329, 1], [8528, 8578, 1], [8581, 8585, 1], [9312, 9371, 1], [9450, 9471, 1], [10102, 10131, 1], [11517, 12295, 778], [12321, 12329, 1], [12344, 12346, 1], [12690, 12693, 1], [12832, 12841, 1], [12872, 12879, 1], [12881, 12895, 1], [12928, 12937, 1], [12977, 12991, 1], [42528, 42537, 1], [42726, 42735, 1], [43056, 43061, 1], [43216, 43225, 1], [43264, 43273, 1], [43472, 43481, 1], [43504, 43513, 1], [43600, 43609, 1], [44016, 44025, 1], [65296, 65305, 1], [65799, 65843, 1], [65856, 65912, 1], [65930, 65931, 1], [66273, 66299, 1], [66336, 66339, 1], [66369, 66378, 9], [66513, 66517, 1], [66720, 66729, 1], [67672, 67679, 1], [67705, 67711, 1], [67751, 67759, 1], [67835, 67839, 1], [67862, 67867, 1], [68028, 68029, 1], [68032, 68047, 1], [68050, 68095, 1], [68160, 68168, 1], [68221, 68222, 1], [68253, 68255, 1], [68331, 68335, 1], [68440, 68447, 1], [68472, 68479, 1], [68521, 68527, 1], [68858, 68863, 1], [68912, 68921, 1], [69216, 69246, 1], [69405, 69414, 1], [69457, 69460, 1], [69573, 69579, 1], [69714, 69743, 1], [69872, 69881, 1], [69942, 69951, 1], [70096, 70105, 1], [70113, 70132, 1], [70384, 70393, 1], [70736, 70745, 1], [70864, 70873, 1], [71248, 71257, 1], [71360, 71369, 1], [71472, 71483, 1], [71904, 71922, 1], [72016, 72025, 1], [72784, 72812, 1], [73040, 73049, 1], [73120, 73129, 1], [73552, 73561, 1], [73664, 73684, 1], [74752, 74862, 1], [92768, 92777, 1], [92864, 92873, 1], [93008, 93017, 1], [93019, 93025, 1], [93824, 93846, 1], [119488, 119507, 1], [119520, 119539, 1], [119648, 119672, 1], [120782, 120831, 1], [123200, 123209, 1], [123632, 123641, 1], [124144, 124153, 1], [125127, 125135, 1], [125264, 125273, 1], [126065, 126123, 1], [126125, 126127, 1], [126129, 126132, 1], [126209, 126253, 1], [126255, 126269, 1], [127232, 127244, 1], [130032, 130041, 1]];
    static Nd = [[48, 57, 1], [1632, 1641, 1], [1776, 1785, 1], [1984, 1993, 1], [2406, 2415, 1], [2534, 2543, 1], [2662, 2671, 1], [2790, 2799, 1], [2918, 2927, 1], [3046, 3055, 1], [3174, 3183, 1], [3302, 3311, 1], [3430, 3439, 1], [3558, 3567, 1], [3664, 3673, 1], [3792, 3801, 1], [3872, 3881, 1], [4160, 4169, 1], [4240, 4249, 1], [6112, 6121, 1], [6160, 6169, 1], [6470, 6479, 1], [6608, 6617, 1], [6784, 6793, 1], [6800, 6809, 1], [6992, 7001, 1], [7088, 7097, 1], [7232, 7241, 1], [7248, 7257, 1], [42528, 42537, 1], [43216, 43225, 1], [43264, 43273, 1], [43472, 43481, 1], [43504, 43513, 1], [43600, 43609, 1], [44016, 44025, 1], [65296, 65305, 1], [66720, 66729, 1], [68912, 68921, 1], [69734, 69743, 1], [69872, 69881, 1], [69942, 69951, 1], [70096, 70105, 1], [70384, 70393, 1], [70736, 70745, 1], [70864, 70873, 1], [71248, 71257, 1], [71360, 71369, 1], [71472, 71481, 1], [71904, 71913, 1], [72016, 72025, 1], [72784, 72793, 1], [73040, 73049, 1], [73120, 73129, 1], [73552, 73561, 1], [92768, 92777, 1], [92864, 92873, 1], [93008, 93017, 1], [120782, 120831, 1], [123200, 123209, 1], [123632, 123641, 1], [124144, 124153, 1], [125264, 125273, 1], [130032, 130041, 1]];
    static Nl = [[5870, 5872, 1], [8544, 8578, 1], [8581, 8584, 1], [12295, 12321, 26], [12322, 12329, 1], [12344, 12346, 1], [42726, 42735, 1], [65856, 65908, 1], [66369, 66378, 9], [66513, 66517, 1], [74752, 74862, 1]];
    static No = [[178, 179, 1], [185, 188, 3], [189, 190, 1], [2548, 2553, 1], [2930, 2935, 1], [3056, 3058, 1], [3192, 3198, 1], [3416, 3422, 1], [3440, 3448, 1], [3882, 3891, 1], [4969, 4988, 1], [6128, 6137, 1], [6618, 8304, 1686], [8308, 8313, 1], [8320, 8329, 1], [8528, 8543, 1], [8585, 9312, 727], [9313, 9371, 1], [9450, 9471, 1], [10102, 10131, 1], [11517, 12690, 1173], [12691, 12693, 1], [12832, 12841, 1], [12872, 12879, 1], [12881, 12895, 1], [12928, 12937, 1], [12977, 12991, 1], [43056, 43061, 1], [65799, 65843, 1], [65909, 65912, 1], [65930, 65931, 1], [66273, 66299, 1], [66336, 66339, 1], [67672, 67679, 1], [67705, 67711, 1], [67751, 67759, 1], [67835, 67839, 1], [67862, 67867, 1], [68028, 68029, 1], [68032, 68047, 1], [68050, 68095, 1], [68160, 68168, 1], [68221, 68222, 1], [68253, 68255, 1], [68331, 68335, 1], [68440, 68447, 1], [68472, 68479, 1], [68521, 68527, 1], [68858, 68863, 1], [69216, 69246, 1], [69405, 69414, 1], [69457, 69460, 1], [69573, 69579, 1], [69714, 69733, 1], [70113, 70132, 1], [71482, 71483, 1], [71914, 71922, 1], [72794, 72812, 1], [73664, 73684, 1], [93019, 93025, 1], [93824, 93846, 1], [119488, 119507, 1], [119520, 119539, 1], [119648, 119672, 1], [125127, 125135, 1], [126065, 126123, 1], [126125, 126127, 1], [126129, 126132, 1], [126209, 126253, 1], [126255, 126269, 1], [127232, 127244, 1]];
    static P = [[33, 35, 1], [37, 42, 1], [44, 47, 1], [58, 59, 1], [63, 64, 1], [91, 93, 1], [95, 123, 28], [125, 161, 36], [167, 171, 4], [182, 183, 1], [187, 191, 4], [894, 903, 9], [1370, 1375, 1], [1417, 1418, 1], [1470, 1472, 2], [1475, 1478, 3], [1523, 1524, 1], [1545, 1546, 1], [1548, 1549, 1], [1563, 1565, 2], [1566, 1567, 1], [1642, 1645, 1], [1748, 1792, 44], [1793, 1805, 1], [2039, 2041, 1], [2096, 2110, 1], [2142, 2404, 262], [2405, 2416, 11], [2557, 2678, 121], [2800, 3191, 391], [3204, 3572, 368], [3663, 3674, 11], [3675, 3844, 169], [3845, 3858, 1], [3860, 3898, 38], [3899, 3901, 1], [3973, 4048, 75], [4049, 4052, 1], [4057, 4058, 1], [4170, 4175, 1], [4347, 4960, 613], [4961, 4968, 1], [5120, 5742, 622], [5787, 5788, 1], [5867, 5869, 1], [5941, 5942, 1], [6100, 6102, 1], [6104, 6106, 1], [6144, 6154, 1], [6468, 6469, 1], [6686, 6687, 1], [6816, 6822, 1], [6824, 6829, 1], [7002, 7008, 1], [7037, 7038, 1], [7164, 7167, 1], [7227, 7231, 1], [7294, 7295, 1], [7360, 7367, 1], [7379, 8208, 829], [8209, 8231, 1], [8240, 8259, 1], [8261, 8273, 1], [8275, 8286, 1], [8317, 8318, 1], [8333, 8334, 1], [8968, 8971, 1], [9001, 9002, 1], [10088, 10101, 1], [10181, 10182, 1], [10214, 10223, 1], [10627, 10648, 1], [10712, 10715, 1], [10748, 10749, 1], [11513, 11516, 1], [11518, 11519, 1], [11632, 11776, 144], [11777, 11822, 1], [11824, 11855, 1], [11858, 11869, 1], [12289, 12291, 1], [12296, 12305, 1], [12308, 12319, 1], [12336, 12349, 13], [12448, 12539, 91], [42238, 42239, 1], [42509, 42511, 1], [42611, 42622, 11], [42738, 42743, 1], [43124, 43127, 1], [43214, 43215, 1], [43256, 43258, 1], [43260, 43310, 50], [43311, 43359, 48], [43457, 43469, 1], [43486, 43487, 1], [43612, 43615, 1], [43742, 43743, 1], [43760, 43761, 1], [44011, 64830, 20819], [64831, 65040, 209], [65041, 65049, 1], [65072, 65106, 1], [65108, 65121, 1], [65123, 65128, 5], [65130, 65131, 1], [65281, 65283, 1], [65285, 65290, 1], [65292, 65295, 1], [65306, 65307, 1], [65311, 65312, 1], [65339, 65341, 1], [65343, 65371, 28], [65373, 65375, 2], [65376, 65381, 1], [65792, 65794, 1], [66463, 66512, 49], [66927, 67671, 744], [67871, 67903, 32], [68176, 68184, 1], [68223, 68336, 113], [68337, 68342, 1], [68409, 68415, 1], [68505, 68508, 1], [69293, 69461, 168], [69462, 69465, 1], [69510, 69513, 1], [69703, 69709, 1], [69819, 69820, 1], [69822, 69825, 1], [69952, 69955, 1], [70004, 70005, 1], [70085, 70088, 1], [70093, 70107, 14], [70109, 70111, 1], [70200, 70205, 1], [70313, 70731, 418], [70732, 70735, 1], [70746, 70747, 1], [70749, 70854, 105], [71105, 71127, 1], [71233, 71235, 1], [71264, 71276, 1], [71353, 71484, 131], [71485, 71486, 1], [71739, 72004, 265], [72005, 72006, 1], [72162, 72255, 93], [72256, 72262, 1], [72346, 72348, 1], [72350, 72354, 1], [72448, 72457, 1], [72769, 72773, 1], [72816, 72817, 1], [73463, 73464, 1], [73539, 73551, 1], [73727, 74864, 1137], [74865, 74868, 1], [77809, 77810, 1], [92782, 92783, 1], [92917, 92983, 66], [92984, 92987, 1], [92996, 93847, 851], [93848, 93850, 1], [94178, 113823, 19645], [121479, 121483, 1], [125278, 125279, 1]];
    static Pc = [[95, 8255, 8160], [8256, 8276, 20], [65075, 65076, 1], [65101, 65103, 1], [65343, 65343, 1]];
    static Pd = [[45, 1418, 1373], [1470, 5120, 3650], [6150, 8208, 2058], [8209, 8213, 1], [11799, 11802, 3], [11834, 11835, 1], [11840, 11869, 29], [12316, 12336, 20], [12448, 65073, 52625], [65074, 65112, 38], [65123, 65293, 170], [69293, 69293, 1]];
    static Pe = [[41, 93, 52], [125, 3899, 3774], [3901, 5788, 1887], [8262, 8318, 56], [8334, 8969, 635], [8971, 9002, 31], [10089, 10101, 2], [10182, 10215, 33], [10217, 10223, 2], [10628, 10648, 2], [10713, 10715, 2], [10749, 11811, 1062], [11813, 11817, 2], [11862, 11868, 2], [12297, 12305, 2], [12309, 12315, 2], [12318, 12319, 1], [64830, 65048, 218], [65078, 65092, 2], [65096, 65114, 18], [65116, 65118, 2], [65289, 65341, 52], [65373, 65379, 3]];
    static Pf = [[187, 8217, 8030], [8221, 8250, 29], [11779, 11781, 2], [11786, 11789, 3], [11805, 11809, 4]];
    static Pi = [[171, 8216, 8045], [8219, 8220, 1], [8223, 8249, 26], [11778, 11780, 2], [11785, 11788, 3], [11804, 11808, 4]];
    static Po = [[33, 35, 1], [37, 39, 1], [42, 46, 2], [47, 58, 11], [59, 63, 4], [64, 92, 28], [161, 167, 6], [182, 183, 1], [191, 894, 703], [903, 1370, 467], [1371, 1375, 1], [1417, 1472, 55], [1475, 1478, 3], [1523, 1524, 1], [1545, 1546, 1], [1548, 1549, 1], [1563, 1565, 2], [1566, 1567, 1], [1642, 1645, 1], [1748, 1792, 44], [1793, 1805, 1], [2039, 2041, 1], [2096, 2110, 1], [2142, 2404, 262], [2405, 2416, 11], [2557, 2678, 121], [2800, 3191, 391], [3204, 3572, 368], [3663, 3674, 11], [3675, 3844, 169], [3845, 3858, 1], [3860, 3973, 113], [4048, 4052, 1], [4057, 4058, 1], [4170, 4175, 1], [4347, 4960, 613], [4961, 4968, 1], [5742, 5867, 125], [5868, 5869, 1], [5941, 5942, 1], [6100, 6102, 1], [6104, 6106, 1], [6144, 6149, 1], [6151, 6154, 1], [6468, 6469, 1], [6686, 6687, 1], [6816, 6822, 1], [6824, 6829, 1], [7002, 7008, 1], [7037, 7038, 1], [7164, 7167, 1], [7227, 7231, 1], [7294, 7295, 1], [7360, 7367, 1], [7379, 8214, 835], [8215, 8224, 9], [8225, 8231, 1], [8240, 8248, 1], [8251, 8254, 1], [8257, 8259, 1], [8263, 8273, 1], [8275, 8277, 2], [8278, 8286, 1], [11513, 11516, 1], [11518, 11519, 1], [11632, 11776, 144], [11777, 11782, 5], [11783, 11784, 1], [11787, 11790, 3], [11791, 11798, 1], [11800, 11801, 1], [11803, 11806, 3], [11807, 11818, 11], [11819, 11822, 1], [11824, 11833, 1], [11836, 11839, 1], [11841, 11843, 2], [11844, 11855, 1], [11858, 11860, 1], [12289, 12291, 1], [12349, 12539, 190], [42238, 42239, 1], [42509, 42511, 1], [42611, 42622, 11], [42738, 42743, 1], [43124, 43127, 1], [43214, 43215, 1], [43256, 43258, 1], [43260, 43310, 50], [43311, 43359, 48], [43457, 43469, 1], [43486, 43487, 1], [43612, 43615, 1], [43742, 43743, 1], [43760, 43761, 1], [44011, 65040, 21029], [65041, 65046, 1], [65049, 65072, 23], [65093, 65094, 1], [65097, 65100, 1], [65104, 65106, 1], [65108, 65111, 1], [65119, 65121, 1], [65128, 65130, 2], [65131, 65281, 150], [65282, 65283, 1], [65285, 65287, 1], [65290, 65294, 2], [65295, 65306, 11], [65307, 65311, 4], [65312, 65340, 28], [65377, 65380, 3], [65381, 65792, 411], [65793, 65794, 1], [66463, 66512, 49], [66927, 67671, 744], [67871, 67903, 32], [68176, 68184, 1], [68223, 68336, 113], [68337, 68342, 1], [68409, 68415, 1], [68505, 68508, 1], [69461, 69465, 1], [69510, 69513, 1], [69703, 69709, 1], [69819, 69820, 1], [69822, 69825, 1], [69952, 69955, 1], [70004, 70005, 1], [70085, 70088, 1], [70093, 70107, 14], [70109, 70111, 1], [70200, 70205, 1], [70313, 70731, 418], [70732, 70735, 1], [70746, 70747, 1], [70749, 70854, 105], [71105, 71127, 1], [71233, 71235, 1], [71264, 71276, 1], [71353, 71484, 131], [71485, 71486, 1], [71739, 72004, 265], [72005, 72006, 1], [72162, 72255, 93], [72256, 72262, 1], [72346, 72348, 1], [72350, 72354, 1], [72448, 72457, 1], [72769, 72773, 1], [72816, 72817, 1], [73463, 73464, 1], [73539, 73551, 1], [73727, 74864, 1137], [74865, 74868, 1], [77809, 77810, 1], [92782, 92783, 1], [92917, 92983, 66], [92984, 92987, 1], [92996, 93847, 851], [93848, 93850, 1], [94178, 113823, 19645], [121479, 121483, 1], [125278, 125279, 1]];
    static Ps = [[40, 91, 51], [123, 3898, 3775], [3900, 5787, 1887], [8218, 8222, 4], [8261, 8317, 56], [8333, 8968, 635], [8970, 9001, 31], [10088, 10100, 2], [10181, 10214, 33], [10216, 10222, 2], [10627, 10647, 2], [10712, 10714, 2], [10748, 11810, 1062], [11812, 11816, 2], [11842, 11861, 19], [11863, 11867, 2], [12296, 12304, 2], [12308, 12314, 2], [12317, 64831, 52514], [65047, 65077, 30], [65079, 65091, 2], [65095, 65113, 18], [65115, 65117, 2], [65288, 65339, 51], [65371, 65375, 4], [65378, 65378, 1]];
    static S = [[36, 43, 7], [60, 62, 1], [94, 96, 2], [124, 126, 2], [162, 166, 1], [168, 169, 1], [172, 174, 2], [175, 177, 1], [180, 184, 4], [215, 247, 32], [706, 709, 1], [722, 735, 1], [741, 747, 1], [749, 751, 2], [752, 767, 1], [885, 900, 15], [901, 1014, 113], [1154, 1421, 267], [1422, 1423, 1], [1542, 1544, 1], [1547, 1550, 3], [1551, 1758, 207], [1769, 1789, 20], [1790, 2038, 248], [2046, 2047, 1], [2184, 2546, 362], [2547, 2554, 7], [2555, 2801, 246], [2928, 3059, 131], [3060, 3066, 1], [3199, 3407, 208], [3449, 3647, 198], [3841, 3843, 1], [3859, 3861, 2], [3862, 3863, 1], [3866, 3871, 1], [3892, 3896, 2], [4030, 4037, 1], [4039, 4044, 1], [4046, 4047, 1], [4053, 4056, 1], [4254, 4255, 1], [5008, 5017, 1], [5741, 6107, 366], [6464, 6622, 158], [6623, 6655, 1], [7009, 7018, 1], [7028, 7036, 1], [8125, 8127, 2], [8128, 8129, 1], [8141, 8143, 1], [8157, 8159, 1], [8173, 8175, 1], [8189, 8190, 1], [8260, 8274, 14], [8314, 8316, 1], [8330, 8332, 1], [8352, 8384, 1], [8448, 8449, 1], [8451, 8454, 1], [8456, 8457, 1], [8468, 8470, 2], [8471, 8472, 1], [8478, 8483, 1], [8485, 8489, 2], [8494, 8506, 12], [8507, 8512, 5], [8513, 8516, 1], [8522, 8525, 1], [8527, 8586, 59], [8587, 8592, 5], [8593, 8967, 1], [8972, 9000, 1], [9003, 9254, 1], [9280, 9290, 1], [9372, 9449, 1], [9472, 10087, 1], [10132, 10180, 1], [10183, 10213, 1], [10224, 10626, 1], [10649, 10711, 1], [10716, 10747, 1], [10750, 11123, 1], [11126, 11157, 1], [11159, 11263, 1], [11493, 11498, 1], [11856, 11857, 1], [11904, 11929, 1], [11931, 12019, 1], [12032, 12245, 1], [12272, 12287, 1], [12292, 12306, 14], [12307, 12320, 13], [12342, 12343, 1], [12350, 12351, 1], [12443, 12444, 1], [12688, 12689, 1], [12694, 12703, 1], [12736, 12771, 1], [12783, 12800, 17], [12801, 12830, 1], [12842, 12871, 1], [12880, 12896, 16], [12897, 12927, 1], [12938, 12976, 1], [12992, 13311, 1], [19904, 19967, 1], [42128, 42182, 1], [42752, 42774, 1], [42784, 42785, 1], [42889, 42890, 1], [43048, 43051, 1], [43062, 43065, 1], [43639, 43641, 1], [43867, 43882, 15], [43883, 64297, 20414], [64434, 64450, 1], [64832, 64847, 1], [64975, 65020, 45], [65021, 65023, 1], [65122, 65124, 2], [65125, 65126, 1], [65129, 65284, 155], [65291, 65308, 17], [65309, 65310, 1], [65342, 65344, 2], [65372, 65374, 2], [65504, 65510, 1], [65512, 65518, 1], [65532, 65533, 1], [65847, 65855, 1], [65913, 65929, 1], [65932, 65934, 1], [65936, 65948, 1], [65952, 66000, 48], [66001, 66044, 1], [67703, 67704, 1], [68296, 71487, 3191], [73685, 73713, 1], [92988, 92991, 1], [92997, 113820, 20823], [118608, 118723, 1], [118784, 119029, 1], [119040, 119078, 1], [119081, 119140, 1], [119146, 119148, 1], [119171, 119172, 1], [119180, 119209, 1], [119214, 119274, 1], [119296, 119361, 1], [119365, 119552, 187], [119553, 119638, 1], [120513, 120539, 26], [120571, 120597, 26], [120629, 120655, 26], [120687, 120713, 26], [120745, 120771, 26], [120832, 121343, 1], [121399, 121402, 1], [121453, 121460, 1], [121462, 121475, 1], [121477, 121478, 1], [123215, 123647, 432], [126124, 126128, 4], [126254, 126704, 450], [126705, 126976, 271], [126977, 127019, 1], [127024, 127123, 1], [127136, 127150, 1], [127153, 127167, 1], [127169, 127183, 1], [127185, 127221, 1], [127245, 127405, 1], [127462, 127490, 1], [127504, 127547, 1], [127552, 127560, 1], [127568, 127569, 1], [127584, 127589, 1], [127744, 128727, 1], [128732, 128748, 1], [128752, 128764, 1], [128768, 128886, 1], [128891, 128985, 1], [128992, 129003, 1], [129008, 129024, 16], [129025, 129035, 1], [129040, 129095, 1], [129104, 129113, 1], [129120, 129159, 1], [129168, 129197, 1], [129200, 129201, 1], [129280, 129619, 1], [129632, 129645, 1], [129648, 129660, 1], [129664, 129672, 1], [129680, 129725, 1], [129727, 129733, 1], [129742, 129755, 1], [129760, 129768, 1], [129776, 129784, 1], [129792, 129938, 1], [129940, 129994, 1]];
    static Sc = [[36, 162, 126], [163, 165, 1], [1423, 1547, 124], [2046, 2047, 1], [2546, 2547, 1], [2555, 2801, 246], [3065, 3647, 582], [6107, 8352, 2245], [8353, 8384, 1], [43064, 65020, 21956], [65129, 65284, 155], [65504, 65505, 1], [65509, 65510, 1], [73693, 73696, 1], [123647, 126128, 2481]];
    static Sk = [[94, 96, 2], [168, 175, 7], [180, 184, 4], [706, 709, 1], [722, 735, 1], [741, 747, 1], [749, 751, 2], [752, 767, 1], [885, 900, 15], [901, 2184, 1283], [8125, 8127, 2], [8128, 8129, 1], [8141, 8143, 1], [8157, 8159, 1], [8173, 8175, 1], [8189, 8190, 1], [12443, 12444, 1], [42752, 42774, 1], [42784, 42785, 1], [42889, 42890, 1], [43867, 43882, 15], [43883, 64434, 20551], [64435, 64450, 1], [65342, 65344, 2], [65507, 127995, 62488], [127996, 127999, 1]];
    static Sm = [[43, 60, 17], [61, 62, 1], [124, 126, 2], [172, 177, 5], [215, 247, 32], [1014, 1542, 528], [1543, 1544, 1], [8260, 8274, 14], [8314, 8316, 1], [8330, 8332, 1], [8472, 8512, 40], [8513, 8516, 1], [8523, 8592, 69], [8593, 8596, 1], [8602, 8603, 1], [8608, 8614, 3], [8622, 8654, 32], [8655, 8658, 3], [8660, 8692, 32], [8693, 8959, 1], [8992, 8993, 1], [9084, 9115, 31], [9116, 9139, 1], [9180, 9185, 1], [9655, 9665, 10], [9720, 9727, 1], [9839, 10176, 337], [10177, 10180, 1], [10183, 10213, 1], [10224, 10239, 1], [10496, 10626, 1], [10649, 10711, 1], [10716, 10747, 1], [10750, 11007, 1], [11056, 11076, 1], [11079, 11084, 1], [64297, 65122, 825], [65124, 65126, 1], [65291, 65308, 17], [65309, 65310, 1], [65372, 65374, 2], [65506, 65513, 7], [65514, 65516, 1], [120513, 120539, 26], [120571, 120597, 26], [120629, 120655, 26], [120687, 120713, 26], [120745, 120771, 26], [126704, 126705, 1]];
    static So = [[166, 169, 3], [174, 176, 2], [1154, 1421, 267], [1422, 1550, 128], [1551, 1758, 207], [1769, 1789, 20], [1790, 2038, 248], [2554, 2928, 374], [3059, 3064, 1], [3066, 3199, 133], [3407, 3449, 42], [3841, 3843, 1], [3859, 3861, 2], [3862, 3863, 1], [3866, 3871, 1], [3892, 3896, 2], [4030, 4037, 1], [4039, 4044, 1], [4046, 4047, 1], [4053, 4056, 1], [4254, 4255, 1], [5008, 5017, 1], [5741, 6464, 723], [6622, 6655, 1], [7009, 7018, 1], [7028, 7036, 1], [8448, 8449, 1], [8451, 8454, 1], [8456, 8457, 1], [8468, 8470, 2], [8471, 8478, 7], [8479, 8483, 1], [8485, 8489, 2], [8494, 8506, 12], [8507, 8522, 15], [8524, 8525, 1], [8527, 8586, 59], [8587, 8597, 10], [8598, 8601, 1], [8604, 8607, 1], [8609, 8610, 1], [8612, 8613, 1], [8615, 8621, 1], [8623, 8653, 1], [8656, 8657, 1], [8659, 8661, 2], [8662, 8691, 1], [8960, 8967, 1], [8972, 8991, 1], [8994, 9000, 1], [9003, 9083, 1], [9085, 9114, 1], [9140, 9179, 1], [9186, 9254, 1], [9280, 9290, 1], [9372, 9449, 1], [9472, 9654, 1], [9656, 9664, 1], [9666, 9719, 1], [9728, 9838, 1], [9840, 10087, 1], [10132, 10175, 1], [10240, 10495, 1], [11008, 11055, 1], [11077, 11078, 1], [11085, 11123, 1], [11126, 11157, 1], [11159, 11263, 1], [11493, 11498, 1], [11856, 11857, 1], [11904, 11929, 1], [11931, 12019, 1], [12032, 12245, 1], [12272, 12287, 1], [12292, 12306, 14], [12307, 12320, 13], [12342, 12343, 1], [12350, 12351, 1], [12688, 12689, 1], [12694, 12703, 1], [12736, 12771, 1], [12783, 12800, 17], [12801, 12830, 1], [12842, 12871, 1], [12880, 12896, 16], [12897, 12927, 1], [12938, 12976, 1], [12992, 13311, 1], [19904, 19967, 1], [42128, 42182, 1], [43048, 43051, 1], [43062, 43063, 1], [43065, 43639, 574], [43640, 43641, 1], [64832, 64847, 1], [64975, 65021, 46], [65022, 65023, 1], [65508, 65512, 4], [65517, 65518, 1], [65532, 65533, 1], [65847, 65855, 1], [65913, 65929, 1], [65932, 65934, 1], [65936, 65948, 1], [65952, 66000, 48], [66001, 66044, 1], [67703, 67704, 1], [68296, 71487, 3191], [73685, 73692, 1], [73697, 73713, 1], [92988, 92991, 1], [92997, 113820, 20823], [118608, 118723, 1], [118784, 119029, 1], [119040, 119078, 1], [119081, 119140, 1], [119146, 119148, 1], [119171, 119172, 1], [119180, 119209, 1], [119214, 119274, 1], [119296, 119361, 1], [119365, 119552, 187], [119553, 119638, 1], [120832, 121343, 1], [121399, 121402, 1], [121453, 121460, 1], [121462, 121475, 1], [121477, 121478, 1], [123215, 126124, 2909], [126254, 126976, 722], [126977, 127019, 1], [127024, 127123, 1], [127136, 127150, 1], [127153, 127167, 1], [127169, 127183, 1], [127185, 127221, 1], [127245, 127405, 1], [127462, 127490, 1], [127504, 127547, 1], [127552, 127560, 1], [127568, 127569, 1], [127584, 127589, 1], [127744, 127994, 1], [128000, 128727, 1], [128732, 128748, 1], [128752, 128764, 1], [128768, 128886, 1], [128891, 128985, 1], [128992, 129003, 1], [129008, 129024, 16], [129025, 129035, 1], [129040, 129095, 1], [129104, 129113, 1], [129120, 129159, 1], [129168, 129197, 1], [129200, 129201, 1], [129280, 129619, 1], [129632, 129645, 1], [129648, 129660, 1], [129664, 129672, 1], [129680, 129725, 1], [129727, 129733, 1], [129742, 129755, 1], [129760, 129768, 1], [129776, 129784, 1], [129792, 129938, 1], [129940, 129994, 1]];
    static Z = [[32, 160, 128], [5760, 8192, 2432], [8193, 8202, 1], [8232, 8233, 1], [8239, 8287, 48], [12288, 12288, 1]];
    static Zl = [[8232, 8232, 1]];
    static Zp = [[8233, 8233, 1]];
    static Zs = [[32, 160, 128], [5760, 8192, 2432], [8193, 8202, 1], [8239, 8287, 48], [12288, 12288, 1]];
    static Adlam = [[125184, 125259, 1], [125264, 125273, 1], [125278, 125279, 1]];
    static Ahom = [[71424, 71450, 1], [71453, 71467, 1], [71472, 71494, 1]];
    static Anatolian_Hieroglyphs = [[82944, 83526, 1]];
    static Arabic = [[1536, 1540, 1], [1542, 1547, 1], [1549, 1562, 1], [1564, 1566, 1], [1568, 1599, 1], [1601, 1610, 1], [1622, 1647, 1], [1649, 1756, 1], [1758, 1791, 1], [1872, 1919, 1], [2160, 2190, 1], [2192, 2193, 1], [2200, 2273, 1], [2275, 2303, 1], [64336, 64450, 1], [64467, 64829, 1], [64832, 64911, 1], [64914, 64967, 1], [64975, 65008, 33], [65009, 65023, 1], [65136, 65140, 1], [65142, 65276, 1], [69216, 69246, 1], [69373, 69375, 1], [126464, 126467, 1], [126469, 126495, 1], [126497, 126498, 1], [126500, 126503, 3], [126505, 126514, 1], [126516, 126519, 1], [126521, 126523, 2], [126530, 126535, 5], [126537, 126541, 2], [126542, 126543, 1], [126545, 126546, 1], [126548, 126551, 3], [126553, 126561, 2], [126562, 126564, 2], [126567, 126570, 1], [126572, 126578, 1], [126580, 126583, 1], [126585, 126588, 1], [126590, 126592, 2], [126593, 126601, 1], [126603, 126619, 1], [126625, 126627, 1], [126629, 126633, 1], [126635, 126651, 1], [126704, 126705, 1]];
    static Armenian = [[1329, 1366, 1], [1369, 1418, 1], [1421, 1423, 1], [64275, 64279, 1]];
    static Avestan = [[68352, 68405, 1], [68409, 68415, 1]];
    static Balinese = [[6912, 6988, 1], [6992, 7038, 1]];
    static Bamum = [[42656, 42743, 1], [92160, 92728, 1]];
    static Bassa_Vah = [[92880, 92909, 1], [92912, 92917, 1]];
    static Batak = [[7104, 7155, 1], [7164, 7167, 1]];
    static Bengali = [[2432, 2435, 1], [2437, 2444, 1], [2447, 2448, 1], [2451, 2472, 1], [2474, 2480, 1], [2482, 2486, 4], [2487, 2489, 1], [2492, 2500, 1], [2503, 2504, 1], [2507, 2510, 1], [2519, 2524, 5], [2525, 2527, 2], [2528, 2531, 1], [2534, 2558, 1]];
    static Bhaiksuki = [[72704, 72712, 1], [72714, 72758, 1], [72760, 72773, 1], [72784, 72812, 1]];
    static Bopomofo = [[746, 747, 1], [12549, 12591, 1], [12704, 12735, 1]];
    static Brahmi = [[69632, 69709, 1], [69714, 69749, 1], [69759, 69759, 1]];
    static Braille = [[10240, 10495, 1]];
    static Buginese = [[6656, 6683, 1], [6686, 6687, 1]];
    static Buhid = [[5952, 5971, 1]];
    static Canadian_Aboriginal = [[5120, 5759, 1], [6320, 6389, 1], [72368, 72383, 1]];
    static Carian = [[66208, 66256, 1]];
    static Caucasian_Albanian = [[66864, 66915, 1], [66927, 66927, 1]];
    static Chakma = [[69888, 69940, 1], [69942, 69959, 1]];
    static Cham = [[43520, 43574, 1], [43584, 43597, 1], [43600, 43609, 1], [43612, 43615, 1]];
    static Cherokee = [[5024, 5109, 1], [5112, 5117, 1], [43888, 43967, 1]];
    static Chorasmian = [[69552, 69579, 1]];
    static Common = [[0, 64, 1], [91, 96, 1], [123, 169, 1], [171, 185, 1], [187, 191, 1], [215, 247, 32], [697, 735, 1], [741, 745, 1], [748, 767, 1], [884, 894, 10], [901, 903, 2], [1541, 1548, 7], [1563, 1567, 4], [1600, 1757, 157], [2274, 2404, 130], [2405, 3647, 1242], [4053, 4056, 1], [4347, 5867, 1520], [5868, 5869, 1], [5941, 5942, 1], [6146, 6147, 1], [6149, 7379, 1230], [7393, 7401, 8], [7402, 7404, 1], [7406, 7411, 1], [7413, 7415, 1], [7418, 8192, 774], [8193, 8203, 1], [8206, 8292, 1], [8294, 8304, 1], [8308, 8318, 1], [8320, 8334, 1], [8352, 8384, 1], [8448, 8485, 1], [8487, 8489, 1], [8492, 8497, 1], [8499, 8525, 1], [8527, 8543, 1], [8585, 8587, 1], [8592, 9254, 1], [9280, 9290, 1], [9312, 10239, 1], [10496, 11123, 1], [11126, 11157, 1], [11159, 11263, 1], [11776, 11869, 1], [12272, 12292, 1], [12294, 12296, 2], [12297, 12320, 1], [12336, 12343, 1], [12348, 12351, 1], [12443, 12444, 1], [12448, 12539, 91], [12540, 12688, 148], [12689, 12703, 1], [12736, 12771, 1], [12783, 12832, 49], [12833, 12895, 1], [12927, 13007, 1], [13055, 13144, 89], [13145, 13311, 1], [19904, 19967, 1], [42752, 42785, 1], [42888, 42890, 1], [43056, 43065, 1], [43310, 43471, 161], [43867, 43882, 15], [43883, 64830, 20947], [64831, 65040, 209], [65041, 65049, 1], [65072, 65106, 1], [65108, 65126, 1], [65128, 65131, 1], [65279, 65281, 2], [65282, 65312, 1], [65339, 65344, 1], [65371, 65381, 1], [65392, 65438, 46], [65439, 65504, 65], [65505, 65510, 1], [65512, 65518, 1], [65529, 65533, 1], [65792, 65794, 1], [65799, 65843, 1], [65847, 65855, 1], [65936, 65948, 1], [66000, 66044, 1], [66273, 66299, 1], [113824, 113827, 1], [118608, 118723, 1], [118784, 119029, 1], [119040, 119078, 1], [119081, 119142, 1], [119146, 119162, 1], [119171, 119172, 1], [119180, 119209, 1], [119214, 119274, 1], [119488, 119507, 1], [119520, 119539, 1], [119552, 119638, 1], [119648, 119672, 1], [119808, 119892, 1], [119894, 119964, 1], [119966, 119967, 1], [119970, 119973, 3], [119974, 119977, 3], [119978, 119980, 1], [119982, 119993, 1], [119995, 119997, 2], [119998, 120003, 1], [120005, 120069, 1], [120071, 120074, 1], [120077, 120084, 1], [120086, 120092, 1], [120094, 120121, 1], [120123, 120126, 1], [120128, 120132, 1], [120134, 120138, 4], [120139, 120144, 1], [120146, 120485, 1], [120488, 120779, 1], [120782, 120831, 1], [126065, 126132, 1], [126209, 126269, 1], [126976, 127019, 1], [127024, 127123, 1], [127136, 127150, 1], [127153, 127167, 1], [127169, 127183, 1], [127185, 127221, 1], [127232, 127405, 1], [127462, 127487, 1], [127489, 127490, 1], [127504, 127547, 1], [127552, 127560, 1], [127568, 127569, 1], [127584, 127589, 1], [127744, 128727, 1], [128732, 128748, 1], [128752, 128764, 1], [128768, 128886, 1], [128891, 128985, 1], [128992, 129003, 1], [129008, 129024, 16], [129025, 129035, 1], [129040, 129095, 1], [129104, 129113, 1], [129120, 129159, 1], [129168, 129197, 1], [129200, 129201, 1], [129280, 129619, 1], [129632, 129645, 1], [129648, 129660, 1], [129664, 129672, 1], [129680, 129725, 1], [129727, 129733, 1], [129742, 129755, 1], [129760, 129768, 1], [129776, 129784, 1], [129792, 129938, 1], [129940, 129994, 1], [130032, 130041, 1], [917505, 917536, 31], [917537, 917631, 1]];
    static foldCommon = [[924, 956, 32]];
    static Coptic = [[994, 1007, 1], [11392, 11507, 1], [11513, 11519, 1]];
    static Cuneiform = [[73728, 74649, 1], [74752, 74862, 1], [74864, 74868, 1], [74880, 75075, 1]];
    static Cypriot = [[67584, 67589, 1], [67592, 67594, 2], [67595, 67637, 1], [67639, 67640, 1], [67644, 67647, 3]];
    static Cypro_Minoan = [[77712, 77810, 1]];
    static Cyrillic = [[1024, 1156, 1], [1159, 1327, 1], [7296, 7304, 1], [7467, 7544, 77], [11744, 11775, 1], [42560, 42655, 1], [65070, 65071, 1], [122928, 122989, 1], [123023, 123023, 1]];
    static Deseret = [[66560, 66639, 1]];
    static Devanagari = [[2304, 2384, 1], [2389, 2403, 1], [2406, 2431, 1], [43232, 43263, 1], [72448, 72457, 1]];
    static Dives_Akuru = [[71936, 71942, 1], [71945, 71948, 3], [71949, 71955, 1], [71957, 71958, 1], [71960, 71989, 1], [71991, 71992, 1], [71995, 72006, 1], [72016, 72025, 1]];
    static Dogra = [[71680, 71739, 1]];
    static Duployan = [[113664, 113770, 1], [113776, 113788, 1], [113792, 113800, 1], [113808, 113817, 1], [113820, 113823, 1]];
    static Egyptian_Hieroglyphs = [[77824, 78933, 1]];
    static Elbasan = [[66816, 66855, 1]];
    static Elymaic = [[69600, 69622, 1]];
    static Ethiopic = [[4608, 4680, 1], [4682, 4685, 1], [4688, 4694, 1], [4696, 4698, 2], [4699, 4701, 1], [4704, 4744, 1], [4746, 4749, 1], [4752, 4784, 1], [4786, 4789, 1], [4792, 4798, 1], [4800, 4802, 2], [4803, 4805, 1], [4808, 4822, 1], [4824, 4880, 1], [4882, 4885, 1], [4888, 4954, 1], [4957, 4988, 1], [4992, 5017, 1], [11648, 11670, 1], [11680, 11686, 1], [11688, 11694, 1], [11696, 11702, 1], [11704, 11710, 1], [11712, 11718, 1], [11720, 11726, 1], [11728, 11734, 1], [11736, 11742, 1], [43777, 43782, 1], [43785, 43790, 1], [43793, 43798, 1], [43808, 43814, 1], [43816, 43822, 1], [124896, 124902, 1], [124904, 124907, 1], [124909, 124910, 1], [124912, 124926, 1]];
    static Georgian = [[4256, 4293, 1], [4295, 4301, 6], [4304, 4346, 1], [4348, 4351, 1], [7312, 7354, 1], [7357, 7359, 1], [11520, 11557, 1], [11559, 11565, 6]];
    static Glagolitic = [[11264, 11359, 1], [122880, 122886, 1], [122888, 122904, 1], [122907, 122913, 1], [122915, 122916, 1], [122918, 122922, 1]];
    static Gothic = [[66352, 66378, 1]];
    static Grantha = [[70400, 70403, 1], [70405, 70412, 1], [70415, 70416, 1], [70419, 70440, 1], [70442, 70448, 1], [70450, 70451, 1], [70453, 70457, 1], [70460, 70468, 1], [70471, 70472, 1], [70475, 70477, 1], [70480, 70487, 7], [70493, 70499, 1], [70502, 70508, 1], [70512, 70516, 1]];
    static Greek = [[880, 883, 1], [885, 887, 1], [890, 893, 1], [895, 900, 5], [902, 904, 2], [905, 906, 1], [908, 910, 2], [911, 929, 1], [931, 993, 1], [1008, 1023, 1], [7462, 7466, 1], [7517, 7521, 1], [7526, 7530, 1], [7615, 7936, 321], [7937, 7957, 1], [7960, 7965, 1], [7968, 8005, 1], [8008, 8013, 1], [8016, 8023, 1], [8025, 8031, 2], [8032, 8061, 1], [8064, 8116, 1], [8118, 8132, 1], [8134, 8147, 1], [8150, 8155, 1], [8157, 8175, 1], [8178, 8180, 1], [8182, 8190, 1], [8486, 43877, 35391], [65856, 65934, 1], [65952, 119296, 53344], [119297, 119365, 1]];
    static foldGreek = [[181, 837, 656]];
    static Gujarati = [[2689, 2691, 1], [2693, 2701, 1], [2703, 2705, 1], [2707, 2728, 1], [2730, 2736, 1], [2738, 2739, 1], [2741, 2745, 1], [2748, 2757, 1], [2759, 2761, 1], [2763, 2765, 1], [2768, 2784, 16], [2785, 2787, 1], [2790, 2801, 1], [2809, 2815, 1]];
    static Gunjala_Gondi = [[73056, 73061, 1], [73063, 73064, 1], [73066, 73102, 1], [73104, 73105, 1], [73107, 73112, 1], [73120, 73129, 1]];
    static Gurmukhi = [[2561, 2563, 1], [2565, 2570, 1], [2575, 2576, 1], [2579, 2600, 1], [2602, 2608, 1], [2610, 2611, 1], [2613, 2614, 1], [2616, 2617, 1], [2620, 2622, 2], [2623, 2626, 1], [2631, 2632, 1], [2635, 2637, 1], [2641, 2649, 8], [2650, 2652, 1], [2654, 2662, 8], [2663, 2678, 1]];
    static Han = [[11904, 11929, 1], [11931, 12019, 1], [12032, 12245, 1], [12293, 12295, 2], [12321, 12329, 1], [12344, 12347, 1], [13312, 19903, 1], [19968, 40959, 1], [63744, 64109, 1], [64112, 64217, 1], [94178, 94179, 1], [94192, 94193, 1], [131072, 173791, 1], [173824, 177977, 1], [177984, 178205, 1], [178208, 183969, 1], [183984, 191456, 1], [191472, 192093, 1], [194560, 195101, 1], [196608, 201546, 1], [201552, 205743, 1]];
    static Hangul = [[4352, 4607, 1], [12334, 12335, 1], [12593, 12686, 1], [12800, 12830, 1], [12896, 12926, 1], [43360, 43388, 1], [44032, 55203, 1], [55216, 55238, 1], [55243, 55291, 1], [65440, 65470, 1], [65474, 65479, 1], [65482, 65487, 1], [65490, 65495, 1], [65498, 65500, 1]];
    static Hanifi_Rohingya = [[68864, 68903, 1], [68912, 68921, 1]];
    static Hanunoo = [[5920, 5940, 1]];
    static Hatran = [[67808, 67826, 1], [67828, 67829, 1], [67835, 67839, 1]];
    static Hebrew = [[1425, 1479, 1], [1488, 1514, 1], [1519, 1524, 1], [64285, 64310, 1], [64312, 64316, 1], [64318, 64320, 2], [64321, 64323, 2], [64324, 64326, 2], [64327, 64335, 1]];
    static Hiragana = [[12353, 12438, 1], [12445, 12447, 1], [110593, 110879, 1], [110898, 110928, 30], [110929, 110930, 1], [127488, 127488, 1]];
    static Imperial_Aramaic = [[67648, 67669, 1], [67671, 67679, 1]];
    static Inherited = [[768, 879, 1], [1157, 1158, 1], [1611, 1621, 1], [1648, 2385, 737], [2386, 2388, 1], [6832, 6862, 1], [7376, 7378, 1], [7380, 7392, 1], [7394, 7400, 1], [7405, 7412, 7], [7416, 7417, 1], [7616, 7679, 1], [8204, 8205, 1], [8400, 8432, 1], [12330, 12333, 1], [12441, 12442, 1], [65024, 65039, 1], [65056, 65069, 1], [66045, 66272, 227], [70459, 118528, 48069], [118529, 118573, 1], [118576, 118598, 1], [119143, 119145, 1], [119163, 119170, 1], [119173, 119179, 1], [119210, 119213, 1], [917760, 917999, 1]];
    static foldInherited = [[921, 953, 32], [8126, 8126, 1]];
    static Inscriptional_Pahlavi = [[68448, 68466, 1], [68472, 68479, 1]];
    static Inscriptional_Parthian = [[68416, 68437, 1], [68440, 68447, 1]];
    static Javanese = [[43392, 43469, 1], [43472, 43481, 1], [43486, 43487, 1]];
    static Kaithi = [[69760, 69826, 1], [69837, 69837, 1]];
    static Kannada = [[3200, 3212, 1], [3214, 3216, 1], [3218, 3240, 1], [3242, 3251, 1], [3253, 3257, 1], [3260, 3268, 1], [3270, 3272, 1], [3274, 3277, 1], [3285, 3286, 1], [3293, 3294, 1], [3296, 3299, 1], [3302, 3311, 1], [3313, 3315, 1]];
    static Katakana = [[12449, 12538, 1], [12541, 12543, 1], [12784, 12799, 1], [13008, 13054, 1], [13056, 13143, 1], [65382, 65391, 1], [65393, 65437, 1], [110576, 110579, 1], [110581, 110587, 1], [110589, 110590, 1], [110592, 110880, 288], [110881, 110882, 1], [110933, 110948, 15], [110949, 110951, 1]];
    static Kawi = [[73472, 73488, 1], [73490, 73530, 1], [73534, 73561, 1]];
    static Kayah_Li = [[43264, 43309, 1], [43311, 43311, 1]];
    static Kharoshthi = [[68096, 68099, 1], [68101, 68102, 1], [68108, 68115, 1], [68117, 68119, 1], [68121, 68149, 1], [68152, 68154, 1], [68159, 68168, 1], [68176, 68184, 1]];
    static Khitan_Small_Script = [[94180, 101120, 6940], [101121, 101589, 1]];
    static Khmer = [[6016, 6109, 1], [6112, 6121, 1], [6128, 6137, 1], [6624, 6655, 1]];
    static Khojki = [[70144, 70161, 1], [70163, 70209, 1]];
    static Khudawadi = [[70320, 70378, 1], [70384, 70393, 1]];
    static Lao = [[3713, 3714, 1], [3716, 3718, 2], [3719, 3722, 1], [3724, 3747, 1], [3749, 3751, 2], [3752, 3773, 1], [3776, 3780, 1], [3782, 3784, 2], [3785, 3790, 1], [3792, 3801, 1], [3804, 3807, 1]];
    static Latin = [[65, 90, 1], [97, 122, 1], [170, 186, 16], [192, 214, 1], [216, 246, 1], [248, 696, 1], [736, 740, 1], [7424, 7461, 1], [7468, 7516, 1], [7522, 7525, 1], [7531, 7543, 1], [7545, 7614, 1], [7680, 7935, 1], [8305, 8319, 14], [8336, 8348, 1], [8490, 8491, 1], [8498, 8526, 28], [8544, 8584, 1], [11360, 11391, 1], [42786, 42887, 1], [42891, 42954, 1], [42960, 42961, 1], [42963, 42965, 2], [42966, 42969, 1], [42994, 43007, 1], [43824, 43866, 1], [43868, 43876, 1], [43878, 43881, 1], [64256, 64262, 1], [65313, 65338, 1], [65345, 65370, 1], [67456, 67461, 1], [67463, 67504, 1], [67506, 67514, 1], [122624, 122654, 1], [122661, 122666, 1]];
    static Lepcha = [[7168, 7223, 1], [7227, 7241, 1], [7245, 7247, 1]];
    static Limbu = [[6400, 6430, 1], [6432, 6443, 1], [6448, 6459, 1], [6464, 6468, 4], [6469, 6479, 1]];
    static Linear_A = [[67072, 67382, 1], [67392, 67413, 1], [67424, 67431, 1]];
    static Linear_B = [[65536, 65547, 1], [65549, 65574, 1], [65576, 65594, 1], [65596, 65597, 1], [65599, 65613, 1], [65616, 65629, 1], [65664, 65786, 1]];
    static Lisu = [[42192, 42239, 1], [73648, 73648, 1]];
    static Lycian = [[66176, 66204, 1]];
    static Lydian = [[67872, 67897, 1], [67903, 67903, 1]];
    static Mahajani = [[69968, 70006, 1]];
    static Makasar = [[73440, 73464, 1]];
    static Malayalam = [[3328, 3340, 1], [3342, 3344, 1], [3346, 3396, 1], [3398, 3400, 1], [3402, 3407, 1], [3412, 3427, 1], [3430, 3455, 1]];
    static Mandaic = [[2112, 2139, 1], [2142, 2142, 1]];
    static Manichaean = [[68288, 68326, 1], [68331, 68342, 1]];
    static Marchen = [[72816, 72847, 1], [72850, 72871, 1], [72873, 72886, 1]];
    static Masaram_Gondi = [[72960, 72966, 1], [72968, 72969, 1], [72971, 73014, 1], [73018, 73020, 2], [73021, 73023, 2], [73024, 73031, 1], [73040, 73049, 1]];
    static Medefaidrin = [[93760, 93850, 1]];
    static Meetei_Mayek = [[43744, 43766, 1], [43968, 44013, 1], [44016, 44025, 1]];
    static Mende_Kikakui = [[124928, 125124, 1], [125127, 125142, 1]];
    static Meroitic_Cursive = [[68000, 68023, 1], [68028, 68047, 1], [68050, 68095, 1]];
    static Meroitic_Hieroglyphs = [[67968, 67999, 1]];
    static Miao = [[93952, 94026, 1], [94031, 94087, 1], [94095, 94111, 1]];
    static Modi = [[71168, 71236, 1], [71248, 71257, 1]];
    static Mongolian = [[6144, 6145, 1], [6148, 6150, 2], [6151, 6169, 1], [6176, 6264, 1], [6272, 6314, 1], [71264, 71276, 1]];
    static Mro = [[92736, 92766, 1], [92768, 92777, 1], [92782, 92783, 1]];
    static Multani = [[70272, 70278, 1], [70280, 70282, 2], [70283, 70285, 1], [70287, 70301, 1], [70303, 70313, 1]];
    static Myanmar = [[4096, 4255, 1], [43488, 43518, 1], [43616, 43647, 1]];
    static Nabataean = [[67712, 67742, 1], [67751, 67759, 1]];
    static Nag_Mundari = [[124112, 124153, 1]];
    static Nandinagari = [[72096, 72103, 1], [72106, 72151, 1], [72154, 72164, 1]];
    static New_Tai_Lue = [[6528, 6571, 1], [6576, 6601, 1], [6608, 6618, 1], [6622, 6623, 1]];
    static Newa = [[70656, 70747, 1], [70749, 70753, 1]];
    static Nko = [[1984, 2042, 1], [2045, 2047, 1]];
    static Nushu = [[94177, 110960, 16783], [110961, 111355, 1]];
    static Nyiakeng_Puachue_Hmong = [[123136, 123180, 1], [123184, 123197, 1], [123200, 123209, 1], [123214, 123215, 1]];
    static Ogham = [[5760, 5788, 1]];
    static Ol_Chiki = [[7248, 7295, 1]];
    static Old_Hungarian = [[68736, 68786, 1], [68800, 68850, 1], [68858, 68863, 1]];
    static Old_Italic = [[66304, 66339, 1], [66349, 66351, 1]];
    static Old_North_Arabian = [[68224, 68255, 1]];
    static Old_Permic = [[66384, 66426, 1]];
    static Old_Persian = [[66464, 66499, 1], [66504, 66517, 1]];
    static Old_Sogdian = [[69376, 69415, 1]];
    static Old_South_Arabian = [[68192, 68223, 1]];
    static Old_Turkic = [[68608, 68680, 1]];
    static Old_Uyghur = [[69488, 69513, 1]];
    static Oriya = [[2817, 2819, 1], [2821, 2828, 1], [2831, 2832, 1], [2835, 2856, 1], [2858, 2864, 1], [2866, 2867, 1], [2869, 2873, 1], [2876, 2884, 1], [2887, 2888, 1], [2891, 2893, 1], [2901, 2903, 1], [2908, 2909, 1], [2911, 2915, 1], [2918, 2935, 1]];
    static Osage = [[66736, 66771, 1], [66776, 66811, 1]];
    static Osmanya = [[66688, 66717, 1], [66720, 66729, 1]];
    static Pahawh_Hmong = [[92928, 92997, 1], [93008, 93017, 1], [93019, 93025, 1], [93027, 93047, 1], [93053, 93071, 1]];
    static Palmyrene = [[67680, 67711, 1]];
    static Pau_Cin_Hau = [[72384, 72440, 1]];
    static Phags_Pa = [[43072, 43127, 1]];
    static Phoenician = [[67840, 67867, 1], [67871, 67871, 1]];
    static Psalter_Pahlavi = [[68480, 68497, 1], [68505, 68508, 1], [68521, 68527, 1]];
    static Rejang = [[43312, 43347, 1], [43359, 43359, 1]];
    static Runic = [[5792, 5866, 1], [5870, 5880, 1]];
    static Samaritan = [[2048, 2093, 1], [2096, 2110, 1]];
    static Saurashtra = [[43136, 43205, 1], [43214, 43225, 1]];
    static Sharada = [[70016, 70111, 1]];
    static Shavian = [[66640, 66687, 1]];
    static Siddham = [[71040, 71093, 1], [71096, 71133, 1]];
    static SignWriting = [[120832, 121483, 1], [121499, 121503, 1], [121505, 121519, 1]];
    static Sinhala = [[3457, 3459, 1], [3461, 3478, 1], [3482, 3505, 1], [3507, 3515, 1], [3517, 3520, 3], [3521, 3526, 1], [3530, 3535, 5], [3536, 3540, 1], [3542, 3544, 2], [3545, 3551, 1], [3558, 3567, 1], [3570, 3572, 1], [70113, 70132, 1]];
    static Sogdian = [[69424, 69465, 1]];
    static Sora_Sompeng = [[69840, 69864, 1], [69872, 69881, 1]];
    static Soyombo = [[72272, 72354, 1]];
    static Sundanese = [[7040, 7103, 1], [7360, 7367, 1]];
    static Syloti_Nagri = [[43008, 43052, 1]];
    static Syriac = [[1792, 1805, 1], [1807, 1866, 1], [1869, 1871, 1], [2144, 2154, 1]];
    static Tagalog = [[5888, 5909, 1], [5919, 5919, 1]];
    static Tagbanwa = [[5984, 5996, 1], [5998, 6000, 1], [6002, 6003, 1]];
    static Tai_Le = [[6480, 6509, 1], [6512, 6516, 1]];
    static Tai_Tham = [[6688, 6750, 1], [6752, 6780, 1], [6783, 6793, 1], [6800, 6809, 1], [6816, 6829, 1]];
    static Tai_Viet = [[43648, 43714, 1], [43739, 43743, 1]];
    static Takri = [[71296, 71353, 1], [71360, 71369, 1]];
    static Tamil = [[2946, 2947, 1], [2949, 2954, 1], [2958, 2960, 1], [2962, 2965, 1], [2969, 2970, 1], [2972, 2974, 2], [2975, 2979, 4], [2980, 2984, 4], [2985, 2986, 1], [2990, 3001, 1], [3006, 3010, 1], [3014, 3016, 1], [3018, 3021, 1], [3024, 3031, 7], [3046, 3066, 1], [73664, 73713, 1], [73727, 73727, 1]];
    static Tangsa = [[92784, 92862, 1], [92864, 92873, 1]];
    static Tangut = [[94176, 94208, 32], [94209, 100343, 1], [100352, 101119, 1], [101632, 101640, 1]];
    static Telugu = [[3072, 3084, 1], [3086, 3088, 1], [3090, 3112, 1], [3114, 3129, 1], [3132, 3140, 1], [3142, 3144, 1], [3146, 3149, 1], [3157, 3158, 1], [3160, 3162, 1], [3165, 3168, 3], [3169, 3171, 1], [3174, 3183, 1], [3191, 3199, 1]];
    static Thaana = [[1920, 1969, 1]];
    static Thai = [[3585, 3642, 1], [3648, 3675, 1]];
    static Tibetan = [[3840, 3911, 1], [3913, 3948, 1], [3953, 3991, 1], [3993, 4028, 1], [4030, 4044, 1], [4046, 4052, 1], [4057, 4058, 1]];
    static Tifinagh = [[11568, 11623, 1], [11631, 11632, 1], [11647, 11647, 1]];
    static Tirhuta = [[70784, 70855, 1], [70864, 70873, 1]];
    static Toto = [[123536, 123566, 1]];
    static Ugaritic = [[66432, 66461, 1], [66463, 66463, 1]];
    static Vai = [[42240, 42539, 1]];
    static Vithkuqi = [[66928, 66938, 1], [66940, 66954, 1], [66956, 66962, 1], [66964, 66965, 1], [66967, 66977, 1], [66979, 66993, 1], [66995, 67001, 1], [67003, 67004, 1]];
    static Wancho = [[123584, 123641, 1], [123647, 123647, 1]];
    static Warang_Citi = [[71840, 71922, 1], [71935, 71935, 1]];
    static Yezidi = [[69248, 69289, 1], [69291, 69293, 1], [69296, 69297, 1]];
    static Yi = [[40960, 42124, 1], [42128, 42182, 1]];
    static Zanabazar_Square = [[72192, 72263, 1]];
    static CATEGORIES = (() => new Map([['C', UnicodeTables.C], ['Cc', UnicodeTables.Cc], ['Cf', UnicodeTables.Cf], ['Co', UnicodeTables.Co], ['Cs', UnicodeTables.Cs], ['L', UnicodeTables.L], ['Ll', UnicodeTables.Ll], ['Lm', UnicodeTables.Lm], ['Lo', UnicodeTables.Lo], ['Lt', UnicodeTables.Lt], ['Lu', UnicodeTables.Lu], ['M', UnicodeTables.M], ['Mc', UnicodeTables.Mc], ['Me', UnicodeTables.Me], ['Mn', UnicodeTables.Mn], ['N', UnicodeTables.N], ['Nd', UnicodeTables.Nd], ['Nl', UnicodeTables.Nl], ['No', UnicodeTables.No], ['P', UnicodeTables.P], ['Pc', UnicodeTables.Pc], ['Pd', UnicodeTables.Pd], ['Pe', UnicodeTables.Pe], ['Pf', UnicodeTables.Pf], ['Pi', UnicodeTables.Pi], ['Po', UnicodeTables.Po], ['Ps', UnicodeTables.Ps], ['S', UnicodeTables.S], ['Sc', UnicodeTables.Sc], ['Sk', UnicodeTables.Sk], ['Sm', UnicodeTables.Sm], ['So', UnicodeTables.So], ['Z', UnicodeTables.Z], ['Zl', UnicodeTables.Zl], ['Zp', UnicodeTables.Zp], ['Zs', UnicodeTables.Zs]]))();
    static SCRIPTS = (() => new Map([['Adlam', UnicodeTables.Adlam], ['Ahom', UnicodeTables.Ahom], ['Anatolian_Hieroglyphs', UnicodeTables.Anatolian_Hieroglyphs], ['Arabic', UnicodeTables.Arabic], ['Armenian', UnicodeTables.Armenian], ['Avestan', UnicodeTables.Avestan], ['Balinese', UnicodeTables.Balinese], ['Bamum', UnicodeTables.Bamum], ['Bassa_Vah', UnicodeTables.Bassa_Vah], ['Batak', UnicodeTables.Batak], ['Bengali', UnicodeTables.Bengali], ['Bhaiksuki', UnicodeTables.Bhaiksuki], ['Bopomofo', UnicodeTables.Bopomofo], ['Brahmi', UnicodeTables.Brahmi], ['Braille', UnicodeTables.Braille], ['Buginese', UnicodeTables.Buginese], ['Buhid', UnicodeTables.Buhid], ['Canadian_Aboriginal', UnicodeTables.Canadian_Aboriginal], ['Carian', UnicodeTables.Carian], ['Caucasian_Albanian', UnicodeTables.Caucasian_Albanian], ['Chakma', UnicodeTables.Chakma], ['Cham', UnicodeTables.Cham], ['Cherokee', UnicodeTables.Cherokee], ['Chorasmian', UnicodeTables.Chorasmian], ['Common', UnicodeTables.Common], ['Coptic', UnicodeTables.Coptic], ['Cuneiform', UnicodeTables.Cuneiform], ['Cypriot', UnicodeTables.Cypriot], ['Cypro_Minoan', UnicodeTables.Cypro_Minoan], ['Cyrillic', UnicodeTables.Cyrillic], ['Deseret', UnicodeTables.Deseret], ['Devanagari', UnicodeTables.Devanagari], ['Dives_Akuru', UnicodeTables.Dives_Akuru], ['Dogra', UnicodeTables.Dogra], ['Duployan', UnicodeTables.Duployan], ['Egyptian_Hieroglyphs', UnicodeTables.Egyptian_Hieroglyphs], ['Elbasan', UnicodeTables.Elbasan], ['Elymaic', UnicodeTables.Elymaic], ['Ethiopic', UnicodeTables.Ethiopic], ['Georgian', UnicodeTables.Georgian], ['Glagolitic', UnicodeTables.Glagolitic], ['Gothic', UnicodeTables.Gothic], ['Grantha', UnicodeTables.Grantha], ['Greek', UnicodeTables.Greek], ['Gujarati', UnicodeTables.Gujarati], ['Gunjala_Gondi', UnicodeTables.Gunjala_Gondi], ['Gurmukhi', UnicodeTables.Gurmukhi], ['Han', UnicodeTables.Han], ['Hangul', UnicodeTables.Hangul], ['Hanifi_Rohingya', UnicodeTables.Hanifi_Rohingya], ['Hanunoo', UnicodeTables.Hanunoo], ['Hatran', UnicodeTables.Hatran], ['Hebrew', UnicodeTables.Hebrew], ['Hiragana', UnicodeTables.Hiragana], ['Imperial_Aramaic', UnicodeTables.Imperial_Aramaic], ['Inherited', UnicodeTables.Inherited], ['Inscriptional_Pahlavi', UnicodeTables.Inscriptional_Pahlavi], ['Inscriptional_Parthian', UnicodeTables.Inscriptional_Parthian], ['Javanese', UnicodeTables.Javanese], ['Kaithi', UnicodeTables.Kaithi], ['Kannada', UnicodeTables.Kannada], ['Katakana', UnicodeTables.Katakana], ['Kawi', UnicodeTables.Kawi], ['Kayah_Li', UnicodeTables.Kayah_Li], ['Kharoshthi', UnicodeTables.Kharoshthi], ['Khitan_Small_Script', UnicodeTables.Khitan_Small_Script], ['Khmer', UnicodeTables.Khmer], ['Khojki', UnicodeTables.Khojki], ['Khudawadi', UnicodeTables.Khudawadi], ['Lao', UnicodeTables.Lao], ['Latin', UnicodeTables.Latin], ['Lepcha', UnicodeTables.Lepcha], ['Limbu', UnicodeTables.Limbu], ['Linear_A', UnicodeTables.Linear_A], ['Linear_B', UnicodeTables.Linear_B], ['Lisu', UnicodeTables.Lisu], ['Lycian', UnicodeTables.Lycian], ['Lydian', UnicodeTables.Lydian], ['Mahajani', UnicodeTables.Mahajani], ['Makasar', UnicodeTables.Makasar], ['Malayalam', UnicodeTables.Malayalam], ['Mandaic', UnicodeTables.Mandaic], ['Manichaean', UnicodeTables.Manichaean], ['Marchen', UnicodeTables.Marchen], ['Masaram_Gondi', UnicodeTables.Masaram_Gondi], ['Medefaidrin', UnicodeTables.Medefaidrin], ['Meetei_Mayek', UnicodeTables.Meetei_Mayek], ['Mende_Kikakui', UnicodeTables.Mende_Kikakui], ['Meroitic_Cursive', UnicodeTables.Meroitic_Cursive], ['Meroitic_Hieroglyphs', UnicodeTables.Meroitic_Hieroglyphs], ['Miao', UnicodeTables.Miao], ['Modi', UnicodeTables.Modi], ['Mongolian', UnicodeTables.Mongolian], ['Mro', UnicodeTables.Mro], ['Multani', UnicodeTables.Multani], ['Myanmar', UnicodeTables.Myanmar], ['Nabataean', UnicodeTables.Nabataean], ['Nag_Mundari', UnicodeTables.Nag_Mundari], ['Nandinagari', UnicodeTables.Nandinagari], ['New_Tai_Lue', UnicodeTables.New_Tai_Lue], ['Newa', UnicodeTables.Newa], ['Nko', UnicodeTables.Nko], ['Nushu', UnicodeTables.Nushu], ['Nyiakeng_Puachue_Hmong', UnicodeTables.Nyiakeng_Puachue_Hmong], ['Ogham', UnicodeTables.Ogham], ['Ol_Chiki', UnicodeTables.Ol_Chiki], ['Old_Hungarian', UnicodeTables.Old_Hungarian], ['Old_Italic', UnicodeTables.Old_Italic], ['Old_North_Arabian', UnicodeTables.Old_North_Arabian], ['Old_Permic', UnicodeTables.Old_Permic], ['Old_Persian', UnicodeTables.Old_Persian], ['Old_Sogdian', UnicodeTables.Old_Sogdian], ['Old_South_Arabian', UnicodeTables.Old_South_Arabian], ['Old_Turkic', UnicodeTables.Old_Turkic], ['Old_Uyghur', UnicodeTables.Old_Uyghur], ['Oriya', UnicodeTables.Oriya], ['Osage', UnicodeTables.Osage], ['Osmanya', UnicodeTables.Osmanya], ['Pahawh_Hmong', UnicodeTables.Pahawh_Hmong], ['Palmyrene', UnicodeTables.Palmyrene], ['Pau_Cin_Hau', UnicodeTables.Pau_Cin_Hau], ['Phags_Pa', UnicodeTables.Phags_Pa], ['Phoenician', UnicodeTables.Phoenician], ['Psalter_Pahlavi', UnicodeTables.Psalter_Pahlavi], ['Rejang', UnicodeTables.Rejang], ['Runic', UnicodeTables.Runic], ['Samaritan', UnicodeTables.Samaritan], ['Saurashtra', UnicodeTables.Saurashtra], ['Sharada', UnicodeTables.Sharada], ['Shavian', UnicodeTables.Shavian], ['Siddham', UnicodeTables.Siddham], ['SignWriting', UnicodeTables.SignWriting], ['Sinhala', UnicodeTables.Sinhala], ['Sogdian', UnicodeTables.Sogdian], ['Sora_Sompeng', UnicodeTables.Sora_Sompeng], ['Soyombo', UnicodeTables.Soyombo], ['Sundanese', UnicodeTables.Sundanese], ['Syloti_Nagri', UnicodeTables.Syloti_Nagri], ['Syriac', UnicodeTables.Syriac], ['Tagalog', UnicodeTables.Tagalog], ['Tagbanwa', UnicodeTables.Tagbanwa], ['Tai_Le', UnicodeTables.Tai_Le], ['Tai_Tham', UnicodeTables.Tai_Tham], ['Tai_Viet', UnicodeTables.Tai_Viet], ['Takri', UnicodeTables.Takri], ['Tamil', UnicodeTables.Tamil], ['Tangsa', UnicodeTables.Tangsa], ['Tangut', UnicodeTables.Tangut], ['Telugu', UnicodeTables.Telugu], ['Thaana', UnicodeTables.Thaana], ['Thai', UnicodeTables.Thai], ['Tibetan', UnicodeTables.Tibetan], ['Tifinagh', UnicodeTables.Tifinagh], ['Tirhuta', UnicodeTables.Tirhuta], ['Toto', UnicodeTables.Toto], ['Ugaritic', UnicodeTables.Ugaritic], ['Vai', UnicodeTables.Vai], ['Vithkuqi', UnicodeTables.Vithkuqi], ['Wancho', UnicodeTables.Wancho], ['Warang_Citi', UnicodeTables.Warang_Citi], ['Yezidi', UnicodeTables.Yezidi], ['Yi', UnicodeTables.Yi], ['Zanabazar_Square', UnicodeTables.Zanabazar_Square]]))();
    static FOLD_CATEGORIES = (() => new Map([['L', UnicodeTables.foldL], ['Ll', UnicodeTables.foldLl], ['Lt', UnicodeTables.foldLt], ['Lu', UnicodeTables.foldLu], ['M', UnicodeTables.foldM], ['Mn', UnicodeTables.foldMn]]))();
    static FOLD_SCRIPT = (() => new Map([['Common', UnicodeTables.foldCommon], ['Greek', UnicodeTables.foldGreek], ['Inherited', UnicodeTables.foldInherited]]))();
  }

  /**
   * Utilities for dealing with Unicode better than JS does.
   */
  class Unicode {
    // The highest legal rune value.
    static MAX_RUNE = 0x10ffff;
    // The highest legal ASCII value.
    static MAX_ASCII = 0x7f;
    // The highest legal Latin-1 value.
    static MAX_LATIN1 = 0xff;
    // The highest legal Basic Multilingual Plane (BMP) value.
    static MAX_BMP = 0xffff;
    // Minimum and maximum runes involved in folding.
    // Checked during test.
    static MIN_FOLD = 0x0041;
    static MAX_FOLD = 0x1e943;

    // is32 uses binary search to test whether rune is in the specified
    // slice of 32-bit ranges.
    static is32(ranges, r) {
      // binary search over ranges
      let lo = 0;
      let hi = ranges.length;
      while (lo < hi) {
        let m = lo + Math.floor((hi - lo) / 2);
        let range = ranges[m];
        if (range[0] <= r && r <= range[1]) {
          return (r - range[0]) % range[2] === 0;
        }
        if (r < range[0]) {
          hi = m;
        } else {
          lo = m + 1;
        }
      }
      return false;
    }

    // is tests whether rune is in the specified table of ranges.
    static is(ranges, r) {
      // common case: rune is ASCII or Latin-1, so use linear search.
      if (r <= this.MAX_LATIN1) {
        for (let range of ranges) {
          // range = [lo, hi, stride]
          if (r > range[1]) {
            continue;
          }
          if (r < range[0]) {
            return false;
          }
          return (r - range[0]) % range[2] === 0;
        }
        return false;
      }
      return ranges.length > 0 && r >= ranges[0][0] && this.is32(ranges, r);
    }

    // isUpper reports whether the rune is an upper case letter.
    static isUpper(r) {
      if (r <= this.MAX_LATIN1) {
        const s = String.fromCodePoint(r);
        return s.toUpperCase() === s && s.toLowerCase() !== s;
      }
      return this.is(UnicodeTables.Upper, r);
    }

    // isPrint reports whether the rune is printable (Unicode L/M/N/P/S or ' ').
    static isPrint(r) {
      if (r <= this.MAX_LATIN1) {
        return r >= 0x20 && r < 0x7f || r >= 0xa1 && r !== 0xad;
      }
      return this.is(UnicodeTables.L, r) || this.is(UnicodeTables.M, r) || this.is(UnicodeTables.N, r) || this.is(UnicodeTables.P, r) || this.is(UnicodeTables.S, r);
    }

    // simpleFold iterates over Unicode code points equivalent under
    // the Unicode-defined simple case folding.  Among the code points
    // equivalent to rune (including rune itself), SimpleFold returns the
    // smallest r >= rune if one exists, or else the smallest r >= 0.
    //
    // For example:
    //      SimpleFold('A') = 'a'
    //      SimpleFold('a') = 'A'
    //
    //      SimpleFold('K') = 'k'
    //      SimpleFold('k') = '\u212A' (Kelvin symbol, K)
    //      SimpleFold('\u212A') = 'K'
    //
    //      SimpleFold('1') = '1'
    //
    // Derived from Go's unicode.SimpleFold.
    //
    static simpleFold(r) {
      // Consult caseOrbit table for special cases.
      if (UnicodeTables.CASE_ORBIT.has(r)) {
        return UnicodeTables.CASE_ORBIT.get(r);
      }

      // No folding specified.  This is a one- or two-element
      // equivalence class containing rune and toLower(rune)
      // and toUpper(rune) if they are different from rune.
      const l = Codepoint.toLowerCase(r);
      if (l !== r) {
        return l;
      }
      return Codepoint.toUpperCase(r);
    }

    // equalsIgnoreCase performs case-insensitive equality comparison
    // on the given runes |r1| and |r2|, with special consideration
    // for the likely scenario where both runes are ASCII characters.
    // If non-ASCII, Unicode case folding will be performed on |r1|
    // to compare it to |r2|.
    // -1 is interpreted as the end-of-file mark.
    static equalsIgnoreCase(r1, r2) {
      // Runes already match, or one of them is EOF
      if (r1 < 0 || r2 < 0 || r1 === r2) {
        return true;
      }

      // Fast path for the common case where both runes are ASCII characters.
      // Coerces both runes to lowercase if applicable.
      if (r1 <= this.MAX_ASCII && r2 <= this.MAX_ASCII) {
        if (Codepoint.CODES.get('A') <= r1 && r1 <= Codepoint.CODES.get('Z')) {
          r1 |= 0x20;
        }
        if (Codepoint.CODES.get('A') <= r2 && r2 <= Codepoint.CODES.get('Z')) {
          r2 |= 0x20;
        }
        return r1 === r2;
      }

      // Fall back to full Unicode case folding otherwise.
      // Invariant: r1 must be non-negative
      for (let r = this.simpleFold(r1); r !== r1; r = this.simpleFold(r)) {
        if (r === r2) {
          return true;
        }
      }
      return false;
    }
  }

  /**
   * Various constants and helper utilities.
   */
  class Utils {
    static METACHARACTERS = '\\.+*?()|[]{}^$';

    //// EMPTY_* flags
    static EMPTY_BEGIN_LINE = 0x01;
    static EMPTY_END_LINE = 0x02;
    static EMPTY_BEGIN_TEXT = 0x04;
    static EMPTY_END_TEXT = 0x08;
    static EMPTY_WORD_BOUNDARY = 0x10;
    static EMPTY_NO_WORD_BOUNDARY = 0x20;
    static EMPTY_ALL = (() => -1)();
    static emptyInts() {
      return [];
    }

    // Returns true iff |c| is an ASCII letter or decimal digit.
    static isalnum(c) {
      return Codepoint.CODES.get('0') <= c && c <= Codepoint.CODES.get('9') || Codepoint.CODES.get('a') <= c && c <= Codepoint.CODES.get('z') || Codepoint.CODES.get('A') <= c && c <= Codepoint.CODES.get('Z');
    }

    // If |c| is an ASCII hex digit, returns its value, otherwise -1.
    static unhex(c) {
      if (Codepoint.CODES.get('0') <= c && c <= Codepoint.CODES.get('9')) {
        return c - Codepoint.CODES.get('0');
      }
      if (Codepoint.CODES.get('a') <= c && c <= Codepoint.CODES.get('f')) {
        return c - Codepoint.CODES.get('a') + 10;
      }
      if (Codepoint.CODES.get('A') <= c && c <= Codepoint.CODES.get('F')) {
        return c - Codepoint.CODES.get('A') + 10;
      }
      return -1;
    }

    // Appends a RE2 literal to |out| for rune |rune|,
    // with regexp metacharacters escaped.
    static escapeRune(rune) {
      let out = '';
      if (Unicode.isPrint(rune)) {
        if (this.METACHARACTERS.indexOf(String.fromCodePoint(rune)) >= 0) {
          out += '\\';
        }
        out += String.fromCodePoint(rune);
      } else {
        switch (rune) {
          case Codepoint.CODES.get('"'):
            // '"'
            out += '\\"';
            break;
          case Codepoint.CODES.get('\\'):
            // '\\'
            out += '\\\\';
            break;
          case Codepoint.CODES.get('\t'):
            // '\t'
            out += '\\t';
            break;
          case Codepoint.CODES.get('\n'):
            // '\n'
            out += '\\n';
            break;
          case Codepoint.CODES.get('\r'):
            // '\r'
            out += '\\r';
            break;
          case Codepoint.CODES.get('\b'):
            // '\b'
            out += '\\b';
            break;
          case Codepoint.CODES.get('\f'):
            // '\f'
            out += '\\f';
            break;
          default:
            {
              let s = rune.toString(16);
              if (rune < 0x100) {
                out += '\\x';
                if (s.length === 1) {
                  out += '0';
                }
                out += s;
              } else {
                out += `\\x{${s}}`;
              }
              break;
            }
        }
      }
      return out;
    }

    // Returns the array of runes in the specified Java UTF-16 string.
    static stringToRunes(str) {
      return String(str).split('').map(s => s.codePointAt(0));
    }

    // Returns the Java UTF-16 string containing the single rune |r|.
    static runeToString(r) {
      return String.fromCodePoint(r);
    }

    // isWordRune reports whether r is consider a ``word character''
    // during the evaluation of the \b and \B zero-width assertions.
    // These assertions are ASCII-only: the word characters are [A-Za-z0-9_].
    static isWordRune(r) {
      return Codepoint.CODES.get('a') <= r && r <= Codepoint.CODES.get('z') || Codepoint.CODES.get('A') <= r && r <= Codepoint.CODES.get('Z') || Codepoint.CODES.get('0') <= r && r <= Codepoint.CODES.get('9') || r === Codepoint.CODES.get('_');
    }

    // emptyOpContext returns the zero-width assertions satisfied at the position
    // between the runes r1 and r2, a bitmask of EMPTY_* flags.
    // Passing r1 == -1 indicates that the position is at the beginning of the
    // text.
    // Passing r2 == -1 indicates that the position is at the end of the text.
    // eslint-disable-next-line no-warning-comments
    // TODO(adonovan): move to Machine.
    static emptyOpContext(r1, r2) {
      let op = 0;
      if (r1 < 0) {
        op |= this.EMPTY_BEGIN_TEXT | this.EMPTY_BEGIN_LINE;
      }
      if (r1 === Codepoint.CODES.get('\n')) {
        op |= this.EMPTY_BEGIN_LINE;
      }
      if (r2 < 0) {
        op |= this.EMPTY_END_TEXT | this.EMPTY_END_LINE;
      }
      if (r2 === Codepoint.CODES.get('\n')) {
        op |= this.EMPTY_END_LINE;
      }
      if (this.isWordRune(r1) !== this.isWordRune(r2)) {
        op |= this.EMPTY_WORD_BOUNDARY;
      } else {
        op |= this.EMPTY_NO_WORD_BOUNDARY;
      }
      return op;
    }

    /**
     * Returns a string that quotes all regular expression metacharacters inside the argument text;
     * the returned string is a regular expression matching the literal text. For example,
     * {@code quoteMeta("[foo]").equals("\\[foo\\]")}.
     * @param {string} s
     * @returns {string}
     */
    static quoteMeta(str) {
      return str.split('') // A char loop is correct because all metacharacters fit in one UTF-16 code.
      .map(s => {
        if (this.METACHARACTERS.indexOf(s) >= 0) {
          return `\\${s}`;
        }
        return s;
      }).join('');
    }
    static charCount(codePoint) {
      return codePoint > Unicode.MAX_BMP ? 2 : 1;
    }
    static stringToUtf8ByteArray(str) {
      if (globalThis.TextEncoder) {
        return Array.from(new TextEncoder().encode(str));
      } else {
        // fallback, if no TextEncoder
        let out = [],
          p = 0;
        for (let i = 0; i < str.length; i++) {
          let c = str.charCodeAt(i);
          if (c < 128) {
            out[p++] = c;
          } else if (c < 2048) {
            out[p++] = c >> 6 | 192;
            out[p++] = c & 63 | 128;
          } else if ((c & 0xfc00) === 0xd800 && i + 1 < str.length && (str.charCodeAt(i + 1) & 0xfc00) === 0xdc00) {
            // Surrogate Pair
            c = 0x10000 + ((c & 0x03ff) << 10) + (str.charCodeAt(++i) & 0x03ff);
            out[p++] = c >> 18 | 240;
            out[p++] = c >> 12 & 63 | 128;
            out[p++] = c >> 6 & 63 | 128;
            out[p++] = c & 63 | 128;
          } else {
            out[p++] = c >> 12 | 224;
            out[p++] = c >> 6 & 63 | 128;
            out[p++] = c & 63 | 128;
          }
        }
        return out;
      }
    }
    static utf8ByteArrayToString(bytes) {
      if (globalThis.TextDecoder) {
        return new TextDecoder('utf-8').decode(new Uint8Array(bytes));
      } else {
        // fallback, if no TextDecoder
        let out = [],
          pos = 0,
          c = 0;
        while (pos < bytes.length) {
          let c1 = bytes[pos++];
          if (c1 < 128) {
            out[c++] = String.fromCharCode(c1);
          } else if (c1 > 191 && c1 < 224) {
            let c2 = bytes[pos++];
            out[c++] = String.fromCharCode((c1 & 31) << 6 | c2 & 63);
          } else if (c1 > 239 && c1 < 365) {
            // Surrogate Pair
            let c2 = bytes[pos++];
            let c3 = bytes[pos++];
            let c4 = bytes[pos++];
            let u = ((c1 & 7) << 18 | (c2 & 63) << 12 | (c3 & 63) << 6 | c4 & 63) - 0x10000;
            out[c++] = String.fromCharCode(0xd800 + (u >> 10));
            out[c++] = String.fromCharCode(0xdc00 + (u & 1023));
          } else {
            let c2 = bytes[pos++];
            let c3 = bytes[pos++];
            out[c++] = String.fromCharCode((c1 & 15) << 12 | (c2 & 63) << 6 | c3 & 63);
          }
        }
        return out.join('');
      }
    }
  }

  // helper to create enums
  // example
  // Encoding[(Encoding['UTF_16'] = 0)] = 'UTF_16'
  // Encoding[(Encoding['UTF_8'] = 1)] = 'UTF_8'
  const createEnum = (values = [], initNum = 0) => {
    const enumObject = {};
    for (let i = 0; i < values.length; i++) {
      const val = values[i];
      const keyVal = initNum + i;
      enumObject[val] = keyVal;
      enumObject[keyVal] = val;
    }
    return Object.freeze(enumObject);
  };

  /**
   * Abstract the representations of input text supplied to Matcher.
   */
  class MatcherInputBase {
    static Encoding = (() => createEnum(['UTF_16', 'UTF_8']))();
    getEncoding() {
      throw Error('not implemented');
    }

    /**
     *
     * @returns {boolean}
     */
    isUTF8Encoding() {
      return this.getEncoding() === MatcherInputBase.Encoding.UTF_8;
    }

    /**
     *
     * @returns {boolean}
     */
    isUTF16Encoding() {
      return this.getEncoding() === MatcherInputBase.Encoding.UTF_16;
    }
  }
  class Utf8MatcherInput extends MatcherInputBase {
    constructor(bytes = null) {
      super();
      this.bytes = bytes;
    }
    getEncoding() {
      return MatcherInputBase.Encoding.UTF_8;
    }
    /**
     *
     * @returns {string}
     */
    asCharSequence() {
      return Utils.utf8ByteArrayToString(this.bytes);
    }

    /**
     *
     * @returns {number[]}
     */
    asBytes() {
      return this.bytes;
    }

    /**
     *
     * @returns {number}
     */
    length() {
      return this.bytes.length;
    }
  }
  class Utf16MatcherInput extends MatcherInputBase {
    constructor(charSequence = null) {
      super();
      this.charSequence = charSequence;
    }
    getEncoding() {
      return MatcherInputBase.Encoding.UTF_16;
    }

    /**
     *
     * @returns {string}
     */
    asCharSequence() {
      return this.charSequence;
    }

    /**
     *
     * @returns {number[]}
     */
    asBytes() {
      return this.charSequence.toString().split('').map(s => s.codePointAt(0));
    }

    /**
     *
     * @returns {number}
     */
    length() {
      return this.charSequence.length;
    }
  }
  class MatcherInput {
    /**
     * Return the MatcherInput for UTF_16 encoding.
     * @returns {Utf16MatcherInput}
     */
    static utf16(charSequence) {
      return new Utf16MatcherInput(charSequence);
    }

    /**
     * Return the MatcherInput for UTF_8 encoding.
     * @returns {Utf8MatcherInput}
     */
    static utf8(input) {
      if (Array.isArray(input)) {
        return new Utf8MatcherInput(input);
      }
      return new Utf8MatcherInput(Utils.stringToUtf8ByteArray(input));
    }
  }

  class RE2JSException extends Error {
    constructor(message) {
      super(message);
      this.name = 'RE2JSException';
    }
  }

  /**
   * An exception thrown by the parser if the pattern was invalid.
   */
  class RE2JSSyntaxException extends RE2JSException {
    constructor(error, input = null) {
      let message = `error parsing regexp: ${error}`;
      if (input) {
        message += `: \`${input}\``;
      }
      super(message);
      this.name = 'RE2JSSyntaxException';
      this.message = message;
      this.error = error;
      this.input = input;
    }

    /**
     * Retrieves the description of the error.
     */
    getDescription() {
      return this.error;
    }

    /**
     * Retrieves the erroneous regular-expression pattern.
     */
    getPattern() {
      return this.input;
    }
  }

  /**
   * An exception thrown by the compiler
   */
  class RE2JSCompileException extends RE2JSException {
    constructor(message) {
      super(message);
      this.name = 'RE2JSCompileException';
    }
  }

  /**
   * An exception thrown by using groups
   */
  class RE2JSGroupException extends RE2JSException {
    constructor(message) {
      super(message);
      this.name = 'RE2JSGroupException';
    }
  }

  /**
   * An exception thrown by flags
   */
  class RE2JSFlagsException extends RE2JSException {
    constructor(message) {
      super(message);
      this.name = 'RE2JSFlagsException';
    }
  }

  /**
   * A stateful iterator that interprets a regex {@code RE2JS} on a specific input.
   *
   * Conceptually, a Matcher consists of four parts:
   * <ol>
   * <li>A compiled regular expression {@code RE2JS}, set at construction and fixed for the lifetime
   * of the matcher.</li>
   *
   * <li>The remainder of the input string, set at construction or {@link #reset()} and advanced by
   * each match operation such as {@link #find}, {@link #matches} or {@link #lookingAt}.</li>
   *
   * <li>The current match information, accessible via {@link #start}, {@link #end}, and
   * {@link #group}, and updated by each match operation.</li>
   *
   * <li>The append position, used and advanced by {@link #appendReplacement} and {@link #appendTail}
   * if performing a search and replace from the input to an external {@code StringBuffer}.
   *
   * </ol>
   *
   *
   * @author rsc@google.com (Russ Cox)
   */
  class Matcher {
    /**
     * Quotes '\' and '$' in {@code s}, so that the returned string could be used in
     * {@link #appendReplacement} as a literal replacement of {@code s}.
     *
     * @param {string} str the string to be quoted
     * @returns {string} the quoted string
     */
    static quoteReplacement(str) {
      if (str.indexOf('\\') < 0 && str.indexOf('$') < 0) {
        return str;
      }
      return str.split('').map(s => {
        const c = s.codePointAt(0);
        if (c === Codepoint.CODES['\\'] || c === Codepoint.CODES['$']) {
          return `\\${s}`;
        }
        return s;
      }).join('');
    }
    /**
     *
     * @param {RE2JS} pattern
     * @param {Utf8MatcherInput|Utf16MatcherInput|number[]|string} input
     */
    constructor(pattern, input) {
      if (pattern === null) {
        throw new Error('pattern is null');
      }
      // The pattern being matched.
      this.patternInput = pattern;
      const re2 = this.patternInput.re2();
      // The number of submatches (groups) in the pattern.
      this.patternGroupCount = re2.numberOfCapturingGroups();
      // The group indexes, in [start, end) pairs.  Zeroth pair is overall match.
      this.groups = [];
      this.namedGroups = re2.namedGroups;
      if (input instanceof MatcherInputBase) {
        this.resetMatcherInput(input);
      } else if (Array.isArray(input)) {
        this.resetMatcherInput(MatcherInput.utf8(input));
      } else {
        this.resetMatcherInput(MatcherInput.utf16(input));
      }
    }

    /**
     * Returns the {@code RE2JS} associated with this {@code Matcher}.
     * @returns {RE2JS}
     */
    pattern() {
      return this.patternInput;
    }

    /**
     * Resets the {@code Matcher}, rewinding input and discarding any match information.
     *
     * @returns {Matcher} the {@code Matcher} itself, for chained method calls
     */
    reset() {
      // The input length in UTF16 codes.
      this.matcherInputLength = this.matcherInput.length();
      // The append position: where the next append should start.
      this.appendPos = 0;
      // Is there a current match?
      this.hasMatch = false;
      // Have we found the submatches (groups) of the current match?
      // group[0], group[1] are set regardless.
      this.hasGroups = false;
      // The anchor flag to use when repeating the match to find subgroups.
      this.anchorFlag = 0;
      return this;
    }

    /**
     * Resets the {@code Matcher} and changes the input.
     * @returns {Matcher} the {@code Matcher} itself, for chained method calls
     */
    resetMatcherInput(input) {
      if (input === null) {
        throw new Error('input is null');
      }
      this.matcherInput = input;
      this.reset();
      return this;
    }

    /**
     * Returns the start of the named group of the most recent match, or -1 if the group was not
     * matched.
     * @param {string|number} [group=0]
     * @returns {string}
     */
    start(group = 0) {
      if (typeof group === 'string') {
        const groupInt = this.namedGroups[group];
        if (!Number.isFinite(groupInt)) {
          throw new RE2JSGroupException(`group '${group}' not found`);
        }
        group = groupInt;
      }
      this.loadGroup(group);
      return this.groups[2 * group];
    }

    /**
     * Returns the end of the named group of the most recent match, or -1 if the group was not
     * matched.
     * @param {string|number} [group=0]
     * @returns {string}
     */
    end(group = 0) {
      if (typeof group === 'string') {
        const groupInt = this.namedGroups[group];
        if (!Number.isFinite(groupInt)) {
          throw new RE2JSGroupException(`group '${group}' not found`);
        }
        group = groupInt;
      }
      this.loadGroup(group);
      return this.groups[2 * group + 1];
    }

    /**
     * Returns the named group of the most recent match, or {@code null} if the group was not matched.
     * @param {string|number} [group=0]
     * @returns {string}
     */
    group(group = 0) {
      if (typeof group === 'string') {
        const groupInt = this.namedGroups[group];
        if (!Number.isFinite(groupInt)) {
          throw new RE2JSGroupException(`group '${group}' not found`);
        }
        group = groupInt;
      }
      const start = this.start(group);
      const end = this.end(group);
      if (start < 0 && end < 0) {
        return null;
      }
      return this.substring(start, end);
    }
    /**
     * Returns the number of subgroups in this pattern.
     *
     * @returns {number} the number of subgroups; the overall match (group 0) does not count
     */
    groupCount() {
      return this.patternGroupCount;
    }

    /**
     * Helper: finds subgroup information if needed for group.
     * @param {number} group
     * @private
     */
    loadGroup(group) {
      if (group < 0 || group > this.patternGroupCount) {
        throw new RE2JSGroupException(`Group index out of bounds: ${group}`);
      }
      if (!this.hasMatch) {
        throw new RE2JSGroupException('perhaps no match attempted');
      }
      if (group === 0 || this.hasGroups) {
        return;
      }
      let end = this.groups[1] + 1;
      if (end > this.matcherInputLength) {
        end = this.matcherInputLength;
      }
      const res = this.patternInput.re2().matchMachineInput(this.matcherInput, this.groups[0], end, this.anchorFlag, 1 + this.patternGroupCount);
      const ok = res[0];
      if (!ok) {
        throw new RE2JSGroupException('inconsistency in matching group data');
      }
      this.groups = res[1];
      this.hasGroups = true;
    }

    /**
     * Matches the entire input against the pattern (anchored start and end). If there is a match,
     * {@code matches} sets the match state to describe it.
     *
     * @returns {boolean} true if the entire input matches the pattern
     */
    matches() {
      return this.genMatch(0, RE2Flags.ANCHOR_BOTH);
    }

    /**
     * Matches the beginning of input against the pattern (anchored start). If there is a match,
     * {@code lookingAt} sets the match state to describe it.
     *
     * @returns {boolean} true if the beginning of the input matches the pattern
     */
    lookingAt() {
      return this.genMatch(0, RE2Flags.ANCHOR_START);
    }

    /**
     * Matches the input against the pattern (unanchored), starting at a specified position. If there
     * is a match, {@code find} sets the match state to describe it.
     *
     * @param {string|number} [start=null] the input position where the search begins
     * @returns {boolean} if it finds a match
     * @throws IndexOutOfBoundsException if start is not a valid input position
     */
    find(start = null) {
      if (start !== null) {
        if (start < 0 || start > this.matcherInputLength) {
          throw new RE2JSGroupException(`start index out of bounds: ${start}`);
        }
        this.reset();
        return this.genMatch(start, 0);
      }
      // no start
      start = 0;
      if (this.hasMatch) {
        start = this.groups[1];
        if (this.groups[0] === this.groups[1]) {
          start++;
        }
      }
      return this.genMatch(start, RE2Flags.UNANCHORED);
    }

    /**
     * Helper: does match starting at start, with RE2 anchor flag.
     * @param {number} startByte
     * @param {number} anchor
     * @returns {boolean}
     * @private
     */
    genMatch(startByte, anchor) {
      const res = this.patternInput.re2().matchMachineInput(this.matcherInput, startByte, this.matcherInputLength, anchor, 1);
      const ok = res[0];
      if (!ok) {
        return false;
      }
      this.groups = res[1];
      this.hasMatch = true;
      this.hasGroups = false;
      this.anchorFlag = anchor;
      return true;
    }

    /**
     * Helper: return substring for [start, end).
     * @param {number} start
     * @param {number} end
     * @returns {string}
     */
    substring(start, end) {
      if (this.matcherInput.isUTF8Encoding()) {
        return Utils.utf8ByteArrayToString(this.matcherInput.asBytes().slice(start, end));
      }
      return this.matcherInput.asCharSequence().substring(start, end).toString();
    }

    /**
     * Helper for Pattern: return input length.
     * @returns {number}
     */
    inputLength() {
      return this.matcherInputLength;
    }

    /**
     * Appends to result two strings: the text from the append position up to the beginning of the
     * most recent match, and then the replacement with submatch groups substituted for references of
     * the form {@code $n}, where {@code n} is the group number in decimal. It advances the append
     * position to where the most recent match ended.
     *
     * To embed a literal {@code $}, use \$ (actually {@code "\\$"} with string escapes). The escape
     * is only necessary when {@code $} is followed by a digit, but it is always allowed. Only
     * {@code $} and {@code \} need escaping, but any character can be escaped.
     *
     * The group number {@code n} in {@code $n} is always at least one digit and expands to use more
     * digits as long as the resulting number is a valid group number for this pattern. To cut it off
     * earlier, escape the first digit that should not be used.
     *
     * @param {string} replacement the replacement string
     * @param {boolean} [perlMode=false] activate perl/js mode (different behaviour for capture groups and special characters)
     * @returns {string}
     * @throws IllegalStateException if there was no most recent match
     * @throws IndexOutOfBoundsException if replacement refers to an invalid group
     * @private
     */
    appendReplacement(replacement, perlMode = false) {
      let res = '';
      const s = this.start();
      const e = this.end();
      if (this.appendPos < s) {
        res += this.substring(this.appendPos, s);
      }
      this.appendPos = e;
      res += perlMode ? this.appendReplacementInternalPerl(replacement) : this.appendReplacementInternal(replacement);
      return res;
    }

    /**
     * @param {string} replacement - the replacement string
     * @returns {string}
     * @private
     */
    appendReplacementInternal(replacement) {
      let res = '';
      let last = 0;
      const m = replacement.length;
      for (let i = 0; i < m - 1; i++) {
        if (replacement.codePointAt(i) === Codepoint.CODES.get('\\')) {
          if (last < i) {
            res += replacement.substring(last, i);
          }
          i++;
          last = i;
          continue;
        }
        if (replacement.codePointAt(i) === Codepoint.CODES.get('$')) {
          let c = replacement.codePointAt(i + 1);
          if (Codepoint.CODES.get('0') <= c && c <= Codepoint.CODES.get('9')) {
            let n = c - Codepoint.CODES.get('0');
            if (last < i) {
              res += replacement.substring(last, i);
            }
            for (i += 2; i < m; i++) {
              c = replacement.codePointAt(i);
              if (c < Codepoint.CODES.get('0') || c > Codepoint.CODES.get('9') || n * 10 + c - Codepoint.CODES.get('0') > this.patternGroupCount) {
                break;
              }
              n = n * 10 + c - Codepoint.CODES.get('0');
            }
            if (n > this.patternGroupCount) {
              throw new RE2JSGroupException(`n > number of groups: ${n}`);
            }
            const group = this.group(n);
            if (group !== null) {
              res += group;
            }
            last = i;
            i--;
            continue;
          } else if (c === Codepoint.CODES.get('{')) {
            if (last < i) {
              res += replacement.substring(last, i);
            }
            i++;
            let j = i + 1;
            while (j < replacement.length && replacement.codePointAt(j) !== Codepoint.CODES.get('}') && replacement.codePointAt(j) !== Codepoint.CODES.get(' ')) {
              j++;
            }
            if (j === replacement.length || replacement.codePointAt(j) !== Codepoint.CODES.get('}')) {
              throw new RE2JSGroupException("named capture group is missing trailing '}'");
            }
            const groupName = replacement.substring(i + 1, j);
            res += this.group(groupName);
            last = j + 1;
          }
        }
      }
      if (last < m) {
        res += replacement.substring(last, m);
      }
      return res;
    }

    /**
     * @param {string} replacement - the replacement string
     * @returns {string}
     * @private
     */
    appendReplacementInternalPerl(replacement) {
      let res = '';
      let last = 0;
      const m = replacement.length;
      for (let i = 0; i < m - 1; i++) {
        if (replacement.codePointAt(i) === Codepoint.CODES.get('$')) {
          let c = replacement.codePointAt(i + 1);
          if (Codepoint.CODES.get('$') === c) {
            if (last < i) {
              res += replacement.substring(last, i);
            }
            res += '$';
            i++;
            last = i + 1;
            continue;
          } else if (Codepoint.CODES.get('&') === c) {
            if (last < i) {
              res += replacement.substring(last, i);
            }
            const group = this.group(0);
            if (group !== null) {
              res += group;
            } else {
              res += '$&';
            }
            i++;
            last = i + 1;
            continue;
          } else if (Codepoint.CODES.get('1') <= c && c <= Codepoint.CODES.get('9')) {
            let n = c - Codepoint.CODES.get('0');
            if (last < i) {
              res += replacement.substring(last, i);
            }
            for (i += 2; i < m; i++) {
              c = replacement.codePointAt(i);
              if (c < Codepoint.CODES.get('0') || c > Codepoint.CODES.get('9') || n * 10 + c - Codepoint.CODES.get('0') > this.patternGroupCount) {
                break;
              }
              n = n * 10 + c - Codepoint.CODES.get('0');
            }
            if (n > this.patternGroupCount) {
              res += `$${n}`;
              last = i;
              i--;
              continue;
            }
            const group = this.group(n);
            if (group !== null) {
              res += group;
            }
            last = i;
            i--;
            continue;
          } else if (c === Codepoint.CODES.get('<')) {
            if (last < i) {
              res += replacement.substring(last, i);
            }
            i++;
            let j = i + 1;
            while (j < replacement.length && replacement.codePointAt(j) !== Codepoint.CODES.get('>') && replacement.codePointAt(j) !== Codepoint.CODES.get(' ')) {
              j++;
            }
            if (j === replacement.length || replacement.codePointAt(j) !== Codepoint.CODES.get('>')) {
              res += replacement.substring(i - 1, j + 1);
              last = j + 1;
              continue;
            }
            const groupName = replacement.substring(i + 1, j);
            if (Object.prototype.hasOwnProperty.call(this.namedGroups, groupName)) {
              res += this.group(groupName);
            } else {
              res += `$<${groupName}>`;
            }
            last = j + 1;
          }
        }
      }
      if (last < m) {
        res += replacement.substring(last, m);
      }
      return res;
    }

    /**
     * Return the substring of the input from the append position to the end of the
     * input.
     * @returns {string}
     */
    appendTail() {
      return this.substring(this.appendPos, this.matcherInputLength);
    }

    /**
     * Returns the input with all matches replaced by {@code replacement}, interpreted as for
     * {@code appendReplacement}.
     *
     * @param {string} replacement - the replacement string
     * @param {boolean} [perlMode=false] - activate perl/js mode (different behaviour for capture groups and special characters)
     * @returns {string} the input string with the matches replaced
     * @throws IndexOutOfBoundsException if replacement refers to an invalid group and perlMode is false
     */
    replaceAll(replacement, perlMode = false) {
      return this.replace(replacement, true, perlMode);
    }

    /**
     * Returns the input with the first match replaced by {@code replacement}, interpreted as for
     * {@code appendReplacement}.
     *
     * @param {string} replacement - the replacement string
     * @param {boolean} [perlMode=false] - activate perl/js mode (different behaviour for capture groups and special characters)
     * @returns {string} the input string with the first match replaced
     * @throws IndexOutOfBoundsException if replacement refers to an invalid group and perlMode is false
     */
    replaceFirst(replacement, perlMode = false) {
      return this.replace(replacement, false, perlMode);
    }

    /**
     * Helper: replaceAll/replaceFirst hybrid.
     * @param {string} replacement - the replacement string
     * @param {boolean} [all=true] - replace all matches
     * @param {boolean} [perlMode=false] - activate perl/js mode (different behaviour for capture groups and special characters)
     * @returns {string}
     * @private
     */
    replace(replacement, all = true, perlMode = false) {
      let res = '';
      this.reset();
      while (this.find()) {
        res += this.appendReplacement(replacement, perlMode);
        if (!all) {
          break;
        }
      }
      res += this.appendTail();
      return res;
    }
  }

  /**
   * MachineInput abstracts different representations of the input text supplied to the Machine. It
   * provides one-character lookahead.
   */
  class MachineInputBase {
    static EOF() {
      return -1 << 3;
    }

    // can we look ahead without losing info?
    canCheckPrefix() {
      return true;
    }

    // Returns the end position in the same units as step().
    endPos() {
      return this.end;
    }
  }

  // An implementation of MachineInput for UTF-8 byte arrays.
  // |pos| and |width| are byte indices.
  class MachineUTF8Input extends MachineInputBase {
    constructor(bytes, start = 0, end = bytes.length) {
      super();
      this.bytes = bytes;
      this.start = start;
      this.end = end;
    }

    // Returns the rune at the specified index; the units are
    // unspecified, but could be UTF-8 byte, UTF-16 char, or rune
    // indices.  Returns the width (in the same units) of the rune in
    // the lower 3 bits, and the rune (Unicode code point) in the high
    // bits.  Never negative, except for EOF which is represented as -1
    // << 3 | 0.
    step(i) {
      i += this.start;
      if (i >= this.end) {
        return MachineInputBase.EOF();
      }
      let x = this.bytes[i++] & 255;
      if ((x & 128) === 0) {
        return x << 3 | 1;
      } else if ((x & 224) === 192) {
        x = x & 31;
        if (i >= this.end) {
          return MachineInputBase.EOF();
        }
        x = x << 6 | this.bytes[i++] & 63;
        return x << 3 | 2;
      } else if ((x & 240) === 224) {
        x = x & 15;
        if (i + 1 >= this.end) {
          return MachineInputBase.EOF();
        }
        x = x << 6 | this.bytes[i++] & 63;
        x = x << 6 | this.bytes[i++] & 63;
        return x << 3 | 3;
      } else {
        x = x & 7;
        if (i + 2 >= this.end) {
          return MachineInputBase.EOF();
        }
        x = x << 6 | this.bytes[i++] & 63;
        x = x << 6 | this.bytes[i++] & 63;
        x = x << 6 | this.bytes[i++] & 63;
        return x << 3 | 4;
      }
    }

    // Returns the index relative to |pos| at which |re2.prefix| is found
    // in this input stream, or a negative value if not found.
    index(re2, pos) {
      pos += this.start;
      const i = this.indexOf(this.bytes, re2.prefixUTF8, pos);
      return i < 0 ? i : i - pos;
    }

    // Returns a bitmask of EMPTY_* flags.
    context(pos) {
      pos += this.start;
      let r1 = -1;
      if (pos > this.start && pos <= this.end) {
        let start = pos - 1;
        r1 = this.bytes[start--];
        if (r1 >= 128) {
          let lim = pos - 4;
          if (lim < this.start) {
            lim = this.start;
          }
          while (start >= lim && (this.bytes[start] & 192) === 128) {
            start--;
          }
          if (start < this.start) {
            start = this.start;
          }
          r1 = this.step(start) >> 3;
        }
      }
      const r2 = pos < this.end ? this.step(pos) >> 3 : -1;
      return Utils.emptyOpContext(r1, r2);
    }

    // Returns the index of the first occurrence of array |target| within
    // array |source| after |fromIndex|, or -1 if not found.
    indexOf(source, target, fromIndex = 0) {
      let targetLength = target.length;
      if (targetLength === 0) {
        return -1;
      }
      let sourceLength = source.length;
      for (let i = fromIndex; i <= sourceLength - targetLength; i++) {
        for (let j = 0; j < targetLength; j++) {
          if (source[i + j] !== target[j]) {
            break;
          } else if (j === targetLength - 1) {
            return i;
          }
        }
      }
      return -1;
    }
  }

  // |pos| and |width| are in JS "char" units.
  class MachineUTF16Input extends MachineInputBase {
    constructor(charSequence, start = 0, end = charSequence.length) {
      super();
      this.charSequence = charSequence;
      this.start = start;
      this.end = end;
    }

    // Returns the rune at the specified index; the units are
    // unspecified, but could be UTF-8 byte, UTF-16 char, or rune
    // indices.  Returns the width (in the same units) of the rune in
    // the lower 3 bits, and the rune (Unicode code point) in the high
    // bits.  Never negative, except for EOF which is represented as -1
    // << 3 | 0.
    step(pos) {
      pos += this.start;
      if (pos < this.end) {
        const rune = this.charSequence.codePointAt(pos);
        return rune << 3 | Utils.charCount(rune);
      } else {
        return MachineInputBase.EOF();
      }
    }

    // Returns the index relative to |pos| at which |re2.prefix| is found
    // in this input stream, or a negative value if not found.
    index(re2, pos) {
      pos += this.start;
      const i = this.charSequence.indexOf(re2.prefix, pos);
      return i < 0 ? i : i - pos;
    }

    // Returns a bitmask of EMPTY_* flags.
    context(pos) {
      pos += this.start;
      const r1 = pos > 0 && pos <= this.charSequence.length ? this.charSequence.codePointAt(pos - 1) : -1;
      const r2 = pos < this.charSequence.length ? this.charSequence.codePointAt(pos) : -1;
      return Utils.emptyOpContext(r1, r2);
    }
  }
  class MachineInput {
    static fromUTF8(bytes, start = 0, end = bytes.length) {
      return new MachineUTF8Input(bytes, start, end);
    }
    static fromUTF16(charSequence, start = 0, end = charSequence.length) {
      return new MachineUTF16Input(charSequence, start, end);
    }
  }

  /**
   * Regular expression abstract syntax tree. Produced by parser, used by compiler. NB, this
   * corresponds to {@code syntax.regexp} in the Go implementation; Go's {@code regexp} is called
   * {@code RE2} in Java.
   */
  class Regexp {
    static Op = (() => createEnum(['NO_MATCH',
    // Matches no strings.
    'EMPTY_MATCH',
    // Matches empty string.
    'LITERAL',
    // Matches runes[] sequence
    'CHAR_CLASS',
    // Matches Runes interpreted as range pair list
    'ANY_CHAR_NOT_NL',
    // Matches any character except '\n'
    'ANY_CHAR',
    // Matches any character
    'BEGIN_LINE',
    // Matches empty string at end of line
    'END_LINE',
    // Matches empty string at end of line
    'BEGIN_TEXT',
    // Matches empty string at beginning of text
    'END_TEXT',
    // Matches empty string at end of text
    'WORD_BOUNDARY',
    // Matches word boundary `\b`
    'NO_WORD_BOUNDARY',
    // Matches word non-boundary `\B`
    'CAPTURE',
    // Capturing subexpr with index cap, optional name name
    'STAR',
    // Matches subs[0] zero or more times.
    'PLUS',
    // Matches subs[0] one or more times.
    'QUEST',
    // Matches subs[0] zero or one times.
    'REPEAT',
    // Matches subs[0] [min, max] times; max=-1 => no limit.
    'CONCAT',
    // Matches concatenation of subs[]
    'ALTERNATE',
    // Matches union of subs[]
    // Pseudo ops, used internally by Parser for parsing stack:
    'LEFT_PAREN', 'VERTICAL_BAR']))();
    static isPseudoOp(op) {
      return op >= Regexp.Op.LEFT_PAREN;
    }
    static emptySubs() {
      return [];
    }
    static quoteIfHyphen(rune) {
      if (rune === Codepoint.CODES.get('-')) {
        return '\\';
      }
      return '';
    }
    static fromRegexp(re) {
      const regex = new Regexp(re.op);
      regex.flags = re.flags;
      regex.subs = re.subs;
      regex.runes = re.runes;
      regex.cap = re.cap;
      regex.min = re.min;
      regex.max = re.max;
      regex.name = re.name;
      regex.namedGroups = re.namedGroups;
      return regex;
    }
    constructor(op) {
      this.op = op; // operator
      this.flags = 0; // bitmap of parse flags
      // subexpressions, if any.  Never null.
      // subs[0] is used as the freelist.
      this.subs = Regexp.emptySubs();
      this.runes = null; // matched runes, for LITERAL, CHAR_CLASS
      this.min = 0; // min for REPEAT
      this.max = 0; // max for REPEAT
      this.cap = 0; // capturing index, for CAPTURE
      this.name = null; // capturing name, for CAPTURE
      this.namedGroups = {}; // map of group name -> capturing index
    }
    reinit() {
      this.flags = 0;
      this.subs = Regexp.emptySubs();
      this.runes = null;
      this.cap = 0;
      this.min = 0;
      this.max = 0;
      this.name = null;
      this.namedGroups = {};
    }
    toString() {
      return this.appendTo();
    }

    // appendTo() appends the Perl syntax for |this| regular expression to out
    appendTo() {
      let out = '';
      switch (this.op) {
        case Regexp.Op.NO_MATCH:
          out += '[^\\x00-\\x{10FFFF}]';
          break;
        case Regexp.Op.EMPTY_MATCH:
          out += '(?:)';
          break;
        case Regexp.Op.STAR:
        case Regexp.Op.PLUS:
        case Regexp.Op.QUEST:
        case Regexp.Op.REPEAT:
          {
            const sub = this.subs[0];
            if (sub.op > Regexp.Op.CAPTURE || sub.op === Regexp.Op.LITERAL && sub.runes.length > 1) {
              out += `(?:${sub.appendTo()})`;
            } else {
              out += sub.appendTo();
            }
            switch (this.op) {
              case Regexp.Op.STAR:
                out += '*';
                break;
              case Regexp.Op.PLUS:
                out += '+';
                break;
              case Regexp.Op.QUEST:
                out += '?';
                break;
              case Regexp.Op.REPEAT:
                out += `{${this.min}`;
                if (this.min !== this.max) {
                  out += ',';
                  if (this.max >= 0) {
                    out += this.max;
                  }
                }
                out += '}';
                break;
            }
            if ((this.flags & RE2Flags.NON_GREEDY) !== 0) {
              out += '?';
            }
            break;
          }
        case Regexp.Op.CONCAT:
          {
            for (let sub of this.subs) {
              if (sub.op === Regexp.Op.ALTERNATE) {
                out += `(?:${sub.appendTo()})`;
              } else {
                out += sub.appendTo();
              }
            }
            break;
          }
        case Regexp.Op.ALTERNATE:
          {
            let sep = '';
            for (let sub of this.subs) {
              out += sep;
              sep = '|';
              out += sub.appendTo();
            }
            break;
          }
        case Regexp.Op.LITERAL:
          if ((this.flags & RE2Flags.FOLD_CASE) !== 0) {
            out += '(?i:';
          }
          for (let rune of this.runes) {
            out += Utils.escapeRune(rune);
          }
          if ((this.flags & RE2Flags.FOLD_CASE) !== 0) {
            out += ')';
          }
          break;
        case Regexp.Op.ANY_CHAR_NOT_NL:
          out += '(?-s:.)';
          break;
        case Regexp.Op.ANY_CHAR:
          out += '(?s:.)';
          break;
        case Regexp.Op.CAPTURE:
          if (this.name === null || this.name.length === 0) {
            out += '(';
          } else {
            out += `(?P<${this.name}>`;
          }
          if (this.subs[0].op !== Regexp.Op.EMPTY_MATCH) {
            out += this.subs[0].appendTo();
          }
          out += ')';
          break;
        case Regexp.Op.BEGIN_TEXT:
          out += '\\A';
          break;
        case Regexp.Op.END_TEXT:
          if ((this.flags & RE2Flags.WAS_DOLLAR) !== 0) {
            out += '(?-m:$)';
          } else {
            out += '\\z';
          }
          break;
        case Regexp.Op.BEGIN_LINE:
          out += '^';
          break;
        case Regexp.Op.END_LINE:
          out += '$';
          break;
        case Regexp.Op.WORD_BOUNDARY:
          out += '\\b';
          break;
        case Regexp.Op.NO_WORD_BOUNDARY:
          out += '\\B';
          break;
        case Regexp.Op.CHAR_CLASS:
          if (this.runes.length % 2 !== 0) {
            out += '[invalid char class]';
            break;
          }
          out += '[';
          if (this.runes.length === 0) {
            out += '^\\x00-\\x{10FFFF}';
          } else if (this.runes[0] === 0 && this.runes[this.runes.length - 1] === Unicode.MAX_RUNE) {
            out += '^';
            for (let i = 1; i < this.runes.length - 1; i += 2) {
              const lo = this.runes[i] + 1;
              const hi = this.runes[i + 1] - 1;
              out += Regexp.quoteIfHyphen(lo);
              out += Utils.escapeRune(lo);
              if (lo !== hi) {
                out += '-';
                out += Regexp.quoteIfHyphen(hi);
                out += Utils.escapeRune(hi);
              }
            }
          } else {
            for (let i = 0; i < this.runes.length; i += 2) {
              const lo = this.runes[i];
              const hi = this.runes[i + 1];
              out += Regexp.quoteIfHyphen(lo);
              out += Utils.escapeRune(lo);
              if (lo !== hi) {
                out += '-';
                out += Regexp.quoteIfHyphen(hi);
                out += Utils.escapeRune(hi);
              }
            }
          }
          out += ']';
          break;
        default:
          out += this.op;
          break;
      }
      return out;
    }

    // maxCap() walks the regexp to find the maximum capture index.
    maxCap() {
      let m = 0;
      if (this.op === Regexp.Op.CAPTURE) {
        m = this.cap;
      }
      if (this.subs !== null) {
        for (let sub of this.subs) {
          const n = sub.maxCap();
          if (m < n) {
            m = n;
          }
        }
      }
      return m;
    }

    // equals() returns true if this and that have identical structure.
    equals(that) {
      if (!(that !== null && that instanceof Regexp)) {
        return false;
      }
      if (this.op !== that.op) {
        return false;
      }
      switch (this.op) {
        case Regexp.Op.END_TEXT:
          {
            if ((this.flags & RE2Flags.WAS_DOLLAR) !== (that.flags & RE2Flags.WAS_DOLLAR)) {
              return false;
            }
            break;
          }
        case Regexp.Op.LITERAL:
        case Regexp.Op.CHAR_CLASS:
          {
            if (this.runes === null && that.runes === null) {
              break;
            }
            if (this.runes === null || that.runes === null) {
              return false;
            }
            if (this.runes.length !== that.runes.length) {
              return false;
            }
            for (let i = 0; i < this.runes.length; i++) {
              if (this.runes[i] !== that.runes[i]) {
                return false;
              }
            }
            break;
          }
        case Regexp.Op.ALTERNATE:
        case Regexp.Op.CONCAT:
          {
            if (this.subs.length !== that.subs.length) {
              return false;
            }
            for (let i = 0; i < this.subs.length; ++i) {
              if (!this.subs[i].equals(that.subs[i])) {
                return false;
              }
            }
            break;
          }
        case Regexp.Op.STAR:
        case Regexp.Op.PLUS:
        case Regexp.Op.QUEST:
          {
            if ((this.flags & RE2Flags.NON_GREEDY) !== (that.flags & RE2Flags.NON_GREEDY) || !this.subs[0].equals(that.subs[0])) {
              return false;
            }
            break;
          }
        case Regexp.Op.REPEAT:
          {
            if ((this.flags & RE2Flags.NON_GREEDY) !== (that.flags & RE2Flags.NON_GREEDY) || this.min !== that.min || this.max !== that.max || !this.subs[0].equals(that.subs[0])) {
              return false;
            }
            break;
          }
        case Regexp.Op.CAPTURE:
          {
            if (this.cap !== that.cap || (this.name === null ? that.name !== null : this.name !== that.name) || !this.subs[0].equals(that.subs[0])) {
              return false;
            }
            break;
          }
      }
      return true;
    }
  }

  /**
   * A single instruction in the regular expression virtual machine.
   *
   * @see http://swtch.com/~rsc/regexp/regexp2.html
   */
  class Inst {
    static ALT = 1;
    static ALT_MATCH = 2;
    static CAPTURE = 3;
    static EMPTY_WIDTH = 4;
    static FAIL = 5;
    static MATCH = 6;
    static NOP = 7;
    static RUNE = 8;
    static RUNE1 = 9;
    static RUNE_ANY = 10;
    static RUNE_ANY_NOT_NL = 11;
    static isRuneOp(op) {
      return Inst.RUNE <= op && op <= Inst.RUNE_ANY_NOT_NL;
    }

    // Returns an RE2 expression matching exactly |runes|.
    static escapeRunes(runes) {
      let out = '"';
      for (let rune of runes) {
        out += Utils.escapeRune(rune);
      }
      out += '"';
      return out;
    }
    constructor(op) {
      this.op = op;
      this.out = 0; // all but MATCH, FAIL
      this.arg = 0; // ALT, ALT_MATCH, CAPTURE, EMPTY_WIDTH
      // length==1 => exact match
      // otherwise a list of [lo,hi] pairs.  hi is *inclusive*.
      this.runes = null;
    }

    // MatchRune returns true if the instruction matches (and consumes) r.
    // It should only be called when op == InstRune.
    matchRune(r) {
      // Special case: single-rune slice is from literal string, not char
      // class.
      if (this.runes.length === 1) {
        const r0 = this.runes[0];
        // If this pattern is case-insensitive, apply Unicode case folding to compare the two runes.
        // Note that this may result in a case-folding loop when executed,
        // so attempt to reduce the chance of that occurring
        // by performing case folding on |r0| from the pattern rather than |r| from the input.
        if ((this.arg & RE2Flags.FOLD_CASE) !== 0) {
          return Unicode.equalsIgnoreCase(r0, r);
        }
        return r === r0;
      }
      // Peek at the first few pairs.
      // Should handle ASCII well.
      for (let j = 0; j < this.runes.length && j <= 8; j += 2) {
        if (r < this.runes[j]) {
          return false;
        }
        if (r <= this.runes[j + 1]) {
          return true;
        }
      }
      // Otherwise binary search.
      let lo = 0;
      let hi = this.runes.length / 2 | 0;
      while (lo < hi) {
        const m = lo + ((hi - lo) / 2 | 0);
        const c = this.runes[2 * m];
        if (c <= r) {
          if (r <= this.runes[2 * m + 1]) {
            return true;
          }
          lo = m + 1;
        } else {
          hi = m;
        }
      }
      return false;
    }
    /**
     *
     * @returns {string}
     */
    toString() {
      switch (this.op) {
        case Inst.ALT:
          return `alt -> ${this.out}, ${this.arg}`;
        case Inst.ALT_MATCH:
          return `altmatch -> ${this.out}, ${this.arg}`;
        case Inst.CAPTURE:
          return `cap ${this.arg} -> ${this.out}`;
        case Inst.EMPTY_WIDTH:
          return `empty ${this.arg} -> ${this.out}`;
        case Inst.MATCH:
          return 'match';
        case Inst.FAIL:
          return 'fail';
        case Inst.NOP:
          return `nop -> ${this.out}`;
        case Inst.RUNE:
          if (this.runes === null) {
            return 'rune <null>';
          }
          return ['rune ', Inst.escapeRunes(this.runes), (this.arg & RE2Flags.FOLD_CASE) !== 0 ? '/i' : '', ' -> ', this.out].join('');
        case Inst.RUNE1:
          return `rune1 ${Inst.escapeRunes(this.runes)} -> ${this.out}`;
        case Inst.RUNE_ANY:
          return `any -> ${this.out}`;
        case Inst.RUNE_ANY_NOT_NL:
          return `anynotnl -> ${this.out}`;
        default:
          throw new Error('unhandled case in Inst.toString');
      }
    }
  }

  /**
   * A Prog is a compiled regular expression program.
   */
  class Prog {
    constructor() {
      this.inst = [];
      this.start = 0; // index of start instruction
      // number of CAPTURE insts in re
      // 2 => implicit ( and ) for whole match $0
      this.numCap = 2;
    }

    // Returns the instruction at the specified pc.
    // Precondition: pc > 0 && pc < numInst().
    getInst(pc) {
      return this.inst[pc];
    }

    // Returns the number of instructions in this program.
    numInst() {
      return this.inst.length;
    }

    // Adds a new instruction to this program, with operator |op| and |pc| equal
    // to |numInst()|.
    addInst(op) {
      this.inst.push(new Inst(op));
    }

    // skipNop() follows any no-op or capturing instructions and returns the
    // resulting instruction.
    skipNop(pc) {
      let i = this.inst[pc];
      while (i.op === Inst.NOP || i.op === Inst.CAPTURE) {
        i = this.inst[pc];
        pc = i.out;
      }
      return i;
    }

    // prefix() returns a pair of a literal string that all matches for the
    // regexp must start with, and a boolean which is true if the prefix is the
    // entire match.  The string is returned by appending to |prefix|.
    prefix() {
      let prefix = '';
      let i = this.skipNop(this.start);
      if (!Inst.isRuneOp(i.op) || i.runes.length !== 1) {
        return [i.op === Inst.MATCH, prefix];
      }
      while (Inst.isRuneOp(i.op) && i.runes.length === 1 && (i.arg & RE2Flags.FOLD_CASE) === 0) {
        prefix += String.fromCodePoint(i.runes[0]);
        i = this.skipNop(i.out);
      }
      return [i.op === Inst.MATCH, prefix];
    }

    // startCond() returns the leading empty-width conditions that must be true
    // in any match.  It returns -1 (all bits set) if no matches are possible.
    startCond() {
      let flag = 0;
      let pc = this.start;
      loop: for (;;) {
        const i = this.inst[pc];
        switch (i.op) {
          case Inst.EMPTY_WIDTH:
            flag |= i.arg;
            break;
          case Inst.FAIL:
            return -1;
          case Inst.CAPTURE:
          case Inst.NOP:
            break;
          default:
            break loop;
        }
        pc = i.out;
      }
      return flag;
    }

    // --- Patch list ---

    // A patchlist is a list of instruction pointers that need to be filled in
    // (patched).  Because the pointers haven't been filled in yet, we can reuse
    // their storage to hold the list.  It's kind of sleazy, but works well in
    // practice.  See http://swtch.com/~rsc/regexp/regexp1.html for inspiration.

    // These aren't really pointers: they're integers, so we can reinterpret them
    // this way without using package unsafe.  A value l denotes p.inst[l>>1].out
    // (l&1==0) or .arg (l&1==1).  l == 0 denotes the empty list, okay because we
    // start every program with a fail instruction, so we'll never want to point
    // at its output link.

    next(l) {
      const i = this.inst[l >> 1];
      if ((l & 1) === 0) {
        return i.out;
      }
      return i.arg;
    }
    patch(l, val) {
      while (l !== 0) {
        const i = this.inst[l >> 1];
        if ((l & 1) === 0) {
          l = i.out;
          i.out = val;
        } else {
          l = i.arg;
          i.arg = val;
        }
      }
    }
    append(l1, l2) {
      if (l1 === 0) {
        return l2;
      }
      if (l2 === 0) {
        return l1;
      }
      let last = l1;
      for (;;) {
        const next = this.next(last);
        if (next === 0) {
          break;
        }
        last = next;
      }
      const i = this.inst[last >> 1];
      if ((last & 1) === 0) {
        i.out = l2;
      } else {
        i.arg = l2;
      }
      return l1;
    }
    /**
     *
     * @returns {string}
     */
    toString() {
      let out = '';
      for (let pc = 0; pc < this.inst.length; pc++) {
        const len = out.length;
        out += pc;
        if (pc === this.start) {
          out += '*';
        }
        out += '        '.substring(out.length - len);
        out += this.inst[pc];
        out += '\n';
      }
      return out;
    }
  }

  /**
   * A fragment of a compiled regular expression program.
   *
   * @see http://swtch.com/~rsc/regexp/regexp1.html
   * @class
   */
  class Frag {
    constructor(i = 0, out = 0, nullable = false) {
      this.i = i; // an instruction address (pc).
      this.out = out; // a patch list; see explanation in Prog.js
      this.nullable = nullable; // whether the fragment can match the empty string
    }
  }
  /**
   * Compiler from {@code Regexp} (RE2 abstract syntax) to {@code RE2} (compiled regular expression).
   *
   * The only entry point is {@link #compileRegexp}.
   */
  class Compiler {
    static ANY_RUNE_NOT_NL() {
      return [0, Codepoint.CODES.get('\n') - 1, Codepoint.CODES.get('\n') + 1, Unicode.MAX_RUNE];
    }
    static ANY_RUNE() {
      return [0, Unicode.MAX_RUNE];
    }
    static compileRegexp(re) {
      const c = new Compiler();
      const f = c.compile(re);
      c.prog.patch(f.out, c.newInst(Inst.MATCH).i);
      c.prog.start = f.i;
      return c.prog;
    }
    constructor() {
      this.prog = new Prog();
      this.newInst(Inst.FAIL);
    }
    newInst(op) {
      this.prog.addInst(op);
      return new Frag(this.prog.numInst() - 1, 0, true);
    }

    // Returns a no-op fragment.  Sometimes unavoidable.
    nop() {
      const f = this.newInst(Inst.NOP);
      f.out = f.i << 1;
      return f;
    }
    fail() {
      return new Frag();
    }

    // Given fragment a, returns (a) capturing as \n.
    // Given a fragment a, returns a fragment with capturing parens around a.
    cap(arg) {
      const f = this.newInst(Inst.CAPTURE);
      f.out = f.i << 1;
      this.prog.getInst(f.i).arg = arg;
      if (this.prog.numCap < arg + 1) {
        this.prog.numCap = arg + 1;
      }
      return f;
    }

    // Given fragments a and b, returns ab; a|b
    cat(f1, f2) {
      // concat of failure is failure
      if (f1.i === 0 || f2.i === 0) {
        return this.fail();
      }
      // eslint-disable-next-line no-warning-comments
      // TODO(rsc): elide nop
      this.prog.patch(f1.out, f2.i);
      return new Frag(f1.i, f2.out, f1.nullable && f2.nullable);
    }

    // Given fragments for a and b, returns fragment for a|b.
    alt(f1, f2) {
      // alt of failure is other
      if (f1.i === 0) {
        return f2;
      }
      if (f2.i === 0) {
        return f1;
      }
      const f = this.newInst(Inst.ALT);
      const i = this.prog.getInst(f.i);
      i.out = f1.i;
      i.arg = f2.i;
      f.out = this.prog.append(f1.out, f2.out);
      f.nullable = f1.nullable || f2.nullable;
      return f;
    }

    // loop returns the fragment for the main loop of a plus or star.
    // For plus, it can be used directly. with f1.i as the entry.
    // For star, it can be used directly when f1 can't match an empty string.
    // (When f1 can match an empty string, f1* must be implemented as (f1+)?
    // to get the priority match order correct.)
    loop(f1, nongreedy) {
      const f = this.newInst(Inst.ALT);
      const i = this.prog.getInst(f.i);
      if (nongreedy) {
        i.arg = f1.i;
        f.out = f.i << 1;
      } else {
        i.out = f1.i;
        f.out = f.i << 1 | 1;
      }
      this.prog.patch(f1.out, f.i);
      return f;
    }

    // Given a fragment for a, returns a fragment for a? or a?? (if nongreedy)
    quest(f1, nongreedy) {
      const f = this.newInst(Inst.ALT);
      const i = this.prog.getInst(f.i);
      if (nongreedy) {
        i.arg = f1.i;
        f.out = f.i << 1;
      } else {
        i.out = f1.i;
        f.out = f.i << 1 | 1;
      }
      f.out = this.prog.append(f.out, f1.out);
      return f;
    }

    // Given a fragment a, returns a fragment for a* or a*? (if nongreedy)
    star(f1, nongreedy) {
      if (f1.nullable) {
        return this.quest(this.plus(f1, nongreedy), nongreedy);
      }
      return this.loop(f1, nongreedy);
    }

    // Given a fragment for a, returns a fragment for a+ or a+? (if nongreedy)
    plus(f1, nongreedy) {
      return new Frag(f1.i, this.loop(f1, nongreedy).out, f1.nullable);
    }

    // op is a bitmask of EMPTY_* flags.
    empty(op) {
      const f = this.newInst(Inst.EMPTY_WIDTH);
      this.prog.getInst(f.i).arg = op;
      f.out = f.i << 1;
      return f;
    }

    // flags : parser flags
    rune(runes, flags) {
      const f = this.newInst(Inst.RUNE);
      f.nullable = false;
      const i = this.prog.getInst(f.i);
      i.runes = runes;
      flags &= RE2Flags.FOLD_CASE;
      if (runes.length !== 1 || Unicode.simpleFold(runes[0]) === runes[0]) {
        flags &= ~RE2Flags.FOLD_CASE;
      }
      i.arg = flags;
      f.out = f.i << 1;
      if ((flags & RE2Flags.FOLD_CASE) === 0 && runes.length === 1 || runes.length === 2 && runes[0] === runes[1]) {
        i.op = Inst.RUNE1;
      } else if (runes.length === 2 && runes[0] === 0 && runes[1] === Unicode.MAX_RUNE) {
        i.op = Inst.RUNE_ANY;
      } else if (runes.length === 4 && runes[0] === 0 && runes[1] === Codepoint.CODES.get('\n') - 1 && runes[2] === Codepoint.CODES.get('\n') + 1 && runes[3] === Unicode.MAX_RUNE) {
        i.op = Inst.RUNE_ANY_NOT_NL;
      }
      return f;
    }
    compile(re) {
      switch (re.op) {
        case Regexp.Op.NO_MATCH:
          return this.fail();
        case Regexp.Op.EMPTY_MATCH:
          return this.nop();
        case Regexp.Op.LITERAL:
          if (re.runes.length === 0) {
            return this.nop();
          } else {
            let f = null;
            for (let r of re.runes) {
              const f1 = this.rune([r], re.flags);
              f = f === null ? f1 : this.cat(f, f1);
            }
            return f;
          }
        case Regexp.Op.CHAR_CLASS:
          return this.rune(re.runes, re.flags);
        case Regexp.Op.ANY_CHAR_NOT_NL:
          return this.rune(Compiler.ANY_RUNE_NOT_NL(), 0);
        case Regexp.Op.ANY_CHAR:
          return this.rune(Compiler.ANY_RUNE(), 0);
        case Regexp.Op.BEGIN_LINE:
          return this.empty(Utils.EMPTY_BEGIN_LINE);
        case Regexp.Op.END_LINE:
          return this.empty(Utils.EMPTY_END_LINE);
        case Regexp.Op.BEGIN_TEXT:
          return this.empty(Utils.EMPTY_BEGIN_TEXT);
        case Regexp.Op.END_TEXT:
          return this.empty(Utils.EMPTY_END_TEXT);
        case Regexp.Op.WORD_BOUNDARY:
          return this.empty(Utils.EMPTY_WORD_BOUNDARY);
        case Regexp.Op.NO_WORD_BOUNDARY:
          return this.empty(Utils.EMPTY_NO_WORD_BOUNDARY);
        case Regexp.Op.CAPTURE:
          {
            const bra = this.cap(re.cap << 1);
            const sub = this.compile(re.subs[0]);
            const ket = this.cap(re.cap << 1 | 1);
            return this.cat(this.cat(bra, sub), ket);
          }
        case Regexp.Op.STAR:
          return this.star(this.compile(re.subs[0]), (re.flags & RE2Flags.NON_GREEDY) !== 0);
        case Regexp.Op.PLUS:
          return this.plus(this.compile(re.subs[0]), (re.flags & RE2Flags.NON_GREEDY) !== 0);
        case Regexp.Op.QUEST:
          return this.quest(this.compile(re.subs[0]), (re.flags & RE2Flags.NON_GREEDY) !== 0);
        case Regexp.Op.CONCAT:
          {
            if (re.subs.length === 0) {
              return this.nop();
            } else {
              let f = null;
              for (let sub of re.subs) {
                const f1 = this.compile(sub);
                f = f === null ? f1 : this.cat(f, f1);
              }
              return f;
            }
          }
        case Regexp.Op.ALTERNATE:
          {
            if (re.subs.length === 0) {
              return this.nop();
            } else {
              let f = null;
              for (let sub of re.subs) {
                const f1 = this.compile(sub);
                f = f === null ? f1 : this.alt(f, f1);
              }
              return f;
            }
          }
        default:
          throw new RE2JSCompileException('regexp: unhandled case in compile');
      }
    }
  }

  class Simplify {
    // Simplify returns a regexp equivalent to re but without counted
    // repetitions and with various other simplifications, such as
    // rewriting /(?:a+)+/ to /a+/.  The resulting regexp will execute
    // correctly but its string representation will not produce the same
    // parse tree, because capturing parentheses may have been duplicated
    // or removed.  For example, the simplified form for /(x){1,2}/ is
    // /(x)(x)?/ but both parentheses capture as $1.  The returned regexp
    // may share structure with or be the original.
    static simplify(re) {
      if (re === null) {
        return null;
      }
      switch (re.op) {
        case Regexp.Op.CAPTURE:
        case Regexp.Op.CONCAT:
        case Regexp.Op.ALTERNATE:
          {
            let nre = re;
            for (let i = 0; i < re.subs.length; i++) {
              const sub = re.subs[i];
              const nsub = Simplify.simplify(sub);
              if (nre === re && nsub !== sub) {
                nre = Regexp.fromRegexp(re);
                nre.runes = null;
                nre.subs = re.subs.slice(0, re.subs.length);
              }
              if (nre !== re) {
                nre.subs[i] = nsub;
              }
            }
            return nre;
          }
        case Regexp.Op.STAR:
        case Regexp.Op.PLUS:
        case Regexp.Op.QUEST:
          {
            const sub = Simplify.simplify(re.subs[0]);
            return Simplify.simplify1(re.op, re.flags, sub, re);
          }
        case Regexp.Op.REPEAT:
          {
            // Special special case: x{0} matches the empty string
            // and doesn't even need to consider x.
            if (re.min === 0 && re.max === 0) {
              return new Regexp(Regexp.Op.EMPTY_MATCH);
            }
            // The fun begins.
            const sub = Simplify.simplify(re.subs[0]);

            // x{n,} means at least n matches of x.
            if (re.max === -1) {
              // Special case: x{0,} is x*.
              if (re.min === 0) {
                return Simplify.simplify1(Regexp.Op.STAR, re.flags, sub, null);
              }
              // Special case: x{1,} is x+.
              if (re.min === 1) {
                return Simplify.simplify1(Regexp.Op.PLUS, re.flags, sub, null);
              }
              // General case: x{4,} is xxxx+.
              const nre = new Regexp(Regexp.Op.CONCAT);
              const subs = [];
              for (let i = 0; i < re.min - 1; i++) {
                subs.push(sub);
              }
              subs.push(Simplify.simplify1(Regexp.Op.PLUS, re.flags, sub, null));
              nre.subs = subs.slice(0);
              return nre;
            }
            // Special case x{0} handled above.

            // Special case: x{1} is just x.
            if (re.min === 1 && re.max === 1) {
              return sub;
            }

            // General case: x{n,m} means n copies of x and m copies of x?
            // The machine will do less work if we nest the final m copies,
            // so that x{2,5} = xx(x(x(x)?)?)?

            // Build leading prefix: xx.
            let prefixSubs = null;
            if (re.min > 0) {
              prefixSubs = [];
              for (let i = 0; i < re.min; i++) {
                prefixSubs.push(sub);
              }
            }

            // Build and attach suffix: (x(x(x)?)?)?
            if (re.max > re.min) {
              let suffix = Simplify.simplify1(Regexp.Op.QUEST, re.flags, sub, null);
              for (let i = re.min + 1; i < re.max; i++) {
                const nre2 = new Regexp(Regexp.Op.CONCAT);
                nre2.subs = [sub, suffix];
                suffix = Simplify.simplify1(Regexp.Op.QUEST, re.flags, nre2, null);
              }
              if (prefixSubs === null) {
                return suffix;
              }
              prefixSubs.push(suffix);
            }
            if (prefixSubs !== null) {
              const prefix = new Regexp(Regexp.Op.CONCAT);
              prefix.subs = prefixSubs.slice(0);
              return prefix;
            }

            // Some degenerate case like min > max or min < max < 0.
            // Handle as impossible match.
            return new Regexp(Regexp.Op.NO_MATCH);
          }
      }
      return re;
    }

    // simplify1 implements Simplify for the unary OpStar,
    // OpPlus, and OpQuest operators.  It returns the simple regexp
    // equivalent to
    //
    //      Regexp{Op: op, Flags: flags, Sub: {sub}}
    //
    // under the assumption that sub is already simple, and
    // without first allocating that structure.  If the regexp
    // to be returned turns out to be equivalent to re, simplify1
    // returns re instead.
    //
    // simplify1 is factored out of Simplify because the implementation
    // for other operators generates these unary expressions.
    // Letting them call simplify1 makes sure the expressions they
    // generate are simple.
    static simplify1(op, flags, sub, re) {
      // Special case: repeat the empty string as much as
      // you want, but it's still the empty string.
      if (sub.op === Regexp.Op.EMPTY_MATCH) {
        return sub;
      }

      // The operators are idempotent if the flags match.
      if (op === sub.op && (flags & RE2Flags.NON_GREEDY) === (sub.flags & RE2Flags.NON_GREEDY)) {
        return sub;
      }
      if (re !== null && re.op === op && (re.flags & RE2Flags.NON_GREEDY) === (flags & RE2Flags.NON_GREEDY) && sub === re.subs[0]) {
        return re;
      }
      re = new Regexp(op);
      re.flags = flags;
      re.subs = [sub];
      return re;
    }
  }

  // GENERATED BY tools/scripts/make_perl_groups.pl; DO NOT EDIT.
  // ./tools/scripts/make_perl_groups.pl  > src/CharGroup.js

  class CharGroup {
    constructor(sign, cls) {
      this.sign = sign;
      this.cls = cls;
    }
  }
  const code1 = [0x30, 0x39];
  const code2 = [0x9, 0xa, 0xc, 0xd, 0x20, 0x20];
  const code3 = [0x30, 0x39, 0x41, 0x5a, 0x5f, 0x5f, 0x61, 0x7a];
  const PERL_GROUPS = new Map([['\\d', new CharGroup(+1, code1)], ['\\D', new CharGroup(-1, code1)], ['\\s', new CharGroup(+1, code2)], ['\\S', new CharGroup(-1, code2)], ['\\w', new CharGroup(+1, code3)], ['\\W', new CharGroup(-1, code3)]]);
  const code4 = [0x30, 0x39, 0x41, 0x5a, 0x61, 0x7a];
  const code5 = [0x41, 0x5a, 0x61, 0x7a];
  const code6 = [0x0, 0x7f];
  const code7 = [0x9, 0x9, 0x20, 0x20];
  const code8 = [0x0, 0x1f, 0x7f, 0x7f];
  const code9 = [0x30, 0x39];
  const code10 = [0x21, 0x7e];
  const code11 = [0x61, 0x7a];
  const code12 = [0x20, 0x7e];
  const code13 = [0x21, 0x2f, 0x3a, 0x40, 0x5b, 0x60, 0x7b, 0x7e];
  const code14 = [0x9, 0xd, 0x20, 0x20];
  const code15 = [0x41, 0x5a];
  const code16 = [0x30, 0x39, 0x41, 0x5a, 0x5f, 0x5f, 0x61, 0x7a];
  const code17 = [0x30, 0x39, 0x41, 0x46, 0x61, 0x66];
  const POSIX_GROUPS = new Map([['[:alnum:]', new CharGroup(+1, code4)], ['[:^alnum:]', new CharGroup(-1, code4)], ['[:alpha:]', new CharGroup(+1, code5)], ['[:^alpha:]', new CharGroup(-1, code5)], ['[:ascii:]', new CharGroup(+1, code6)], ['[:^ascii:]', new CharGroup(-1, code6)], ['[:blank:]', new CharGroup(+1, code7)], ['[:^blank:]', new CharGroup(-1, code7)], ['[:cntrl:]', new CharGroup(+1, code8)], ['[:^cntrl:]', new CharGroup(-1, code8)], ['[:digit:]', new CharGroup(+1, code9)], ['[:^digit:]', new CharGroup(-1, code9)], ['[:graph:]', new CharGroup(+1, code10)], ['[:^graph:]', new CharGroup(-1, code10)], ['[:lower:]', new CharGroup(+1, code11)], ['[:^lower:]', new CharGroup(-1, code11)], ['[:print:]', new CharGroup(+1, code12)], ['[:^print:]', new CharGroup(-1, code12)], ['[:punct:]', new CharGroup(+1, code13)], ['[:^punct:]', new CharGroup(-1, code13)], ['[:space:]', new CharGroup(+1, code14)], ['[:^space:]', new CharGroup(-1, code14)], ['[:upper:]', new CharGroup(+1, code15)], ['[:^upper:]', new CharGroup(-1, code15)], ['[:word:]', new CharGroup(+1, code16)], ['[:^word:]', new CharGroup(-1, code16)], ['[:xdigit:]', new CharGroup(+1, code17)], ['[:^xdigit:]', new CharGroup(-1, code17)]]);

  /**
   * A "builder"-style helper class for manipulating character classes represented as an array of
   * pairs of runes [lo, hi], each denoting an inclusive interval.
   *
   * All methods mutate the internal state and return {@code this}, allowing operations to be chained.
   */
  class CharClass {
    // Exposed, since useful for debugging CharGroups too.
    static charClassToString(r, len) {
      let result = '[';
      for (let i = 0; i < len; i += 2) {
        if (i > 0) {
          result += ' ';
        }
        const lo = r[i];
        const hi = r[i + 1];
        if (lo === hi) {
          result += `0x${lo.toString(16)}`;
        } else {
          result += `0x${lo.toString(16)}-0x${hi.toString(16)}`;
        }
      }
      result += ']';
      return result;
    }

    // cmp() returns the ordering of the pair (a[i], a[i+1]) relative to
    // (pivotFrom, pivotTo), where the first component of the pair (lo) is
    // ordered naturally and the second component (hi) is in reverse order.
    static cmp(array, i, pivotFrom, pivotTo) {
      const cmp = array[i] - pivotFrom;
      return cmp !== 0 ? cmp : pivotTo - array[i + 1];
    }

    // qsortIntPair() quicksorts pairs of ints in |array| according to lt().
    // Precondition: |left|, |right|, |this.len| must all be even; |this.len > 1|.
    static qsortIntPair(array, left, right) {
      const pivotIndex = ((left + right) / 2 | 0) & ~1;
      const pivotFrom = array[pivotIndex];
      const pivotTo = array[pivotIndex + 1];
      let i = left;
      let j = right;
      while (i <= j) {
        while (i < right && CharClass.cmp(array, i, pivotFrom, pivotTo) < 0) {
          i += 2;
        }
        while (j > left && CharClass.cmp(array, j, pivotFrom, pivotTo) > 0) {
          j -= 2;
        }
        if (i <= j) {
          if (i !== j) {
            let temp = array[i];
            array[i] = array[j];
            array[j] = temp;
            temp = array[i + 1];
            array[i + 1] = array[j + 1];
            array[j + 1] = temp;
          }
          i += 2;
          j -= 2;
        }
      }
      if (left < j) {
        CharClass.qsortIntPair(array, left, j);
      }
      if (i < right) {
        CharClass.qsortIntPair(array, i, right);
      }
    }
    constructor(r = Utils.emptyInts()) {
      this.r = r; // inclusive ranges, pairs of [lo,hi].  r.length is even.
      this.len = r.length; // prefix of |r| that is defined.  Even.
    }

    // Returns the character class as an int array.  Subsequent CharClass
    // operations may mutate this array, so typically this is the last operation
    // performed on a given CharClass instance.
    toArray() {
      if (this.len === this.r.length) {
        return this.r;
      } else {
        return this.r.slice(0, this.len);
      }
    }

    // cleanClass() sorts the ranges (pairs of elements) of this CharClass,
    // merges them, and eliminates duplicates.
    cleanClass() {
      if (this.len < 4) {
        return this;
      }
      // Sort by lo increasing, hi decreasing to break ties.
      CharClass.qsortIntPair(this.r, 0, this.len - 2);
      // Merge abutting, overlapping.
      let w = 2; // write index
      for (let i = 2; i < this.len; i += 2) {
        {
          const lo = this.r[i];
          const hi = this.r[i + 1];
          if (lo <= this.r[w - 1] + 1) {
            // merge with previous range
            if (hi > this.r[w - 1]) {
              this.r[w - 1] = hi;
            }
            continue;
          }
          // new disjoint range
          this.r[w] = lo;
          this.r[w + 1] = hi;
          w += 2;
        }
      }
      this.len = w;
      return this;
    }

    // appendLiteral() appends the literal |x| to this CharClass.
    appendLiteral(x, flags) {
      return (flags & RE2Flags.FOLD_CASE) !== 0 ? this.appendFoldedRange(x, x) : this.appendRange(x, x);
    }

    // appendRange() appends the range [lo-hi] (inclusive) to this CharClass.
    appendRange(lo, hi) {
      // Expand last range or next to last range if it overlaps or abuts.
      // Checking two ranges helps when appending case-folded
      // alphabets, so that one range can be expanding A-Z and the
      // other expanding a-z.
      if (this.len > 0) {
        for (let i = 2; i <= 4; i += 2) {
          // twice, using i=2, i=4
          if (this.len >= i) {
            const rlo = this.r[this.len - i];
            const rhi = this.r[this.len - i + 1];
            if (lo <= rhi + 1 && rlo <= hi + 1) {
              if (lo < rlo) {
                this.r[this.len - i] = lo;
              }
              if (hi > rhi) {
                this.r[this.len - i + 1] = hi;
              }
              return this;
            }
          }
        }
      }
      this.r[this.len++] = lo;
      this.r[this.len++] = hi;
      return this;
    }

    // appendFoldedRange() appends the range [lo-hi] and its case
    // folding-equivalent runes to this CharClass.
    appendFoldedRange(lo, hi) {
      // Optimizations.
      if (lo <= Unicode.MIN_FOLD && hi >= Unicode.MAX_FOLD) {
        // Range is full: folding can't add more.
        return this.appendRange(lo, hi);
      }
      if (hi < Unicode.MIN_FOLD || lo > Unicode.MAX_FOLD) {
        // Range is outside folding possibilities.
        return this.appendRange(lo, hi);
      }
      if (lo < Unicode.MIN_FOLD) {
        // [lo, minFold-1] needs no folding.
        this.appendRange(lo, Unicode.MIN_FOLD - 1);
        lo = Unicode.MIN_FOLD;
      }
      if (hi > Unicode.MAX_FOLD) {
        // [maxFold+1, hi] needs no folding.
        this.appendRange(Unicode.MAX_FOLD + 1, hi);
        hi = Unicode.MAX_FOLD;
      }

      // Brute force.  Depend on appendRange to coalesce ranges on the fly.
      for (let c = lo; c <= hi; c++) {
        this.appendRange(c, c);
        for (let f = Unicode.simpleFold(c); f !== c; f = Unicode.simpleFold(f)) {
          this.appendRange(f, f);
        }
      }
      return this;
    }

    // appendClass() appends the class |x| to this CharClass.
    // It assumes |x| is clean.  Does not mutate |x|.
    appendClass(x) {
      for (let i = 0; i < x.length; i += 2) {
        this.appendRange(x[i], x[i + 1]);
      }
      return this;
    }

    // appendFoldedClass() appends the case folding of the class |x| to this
    // CharClass.  Does not mutate |x|.
    appendFoldedClass(x) {
      for (let i = 0; i < x.length; i += 2) {
        this.appendFoldedRange(x[i], x[i + 1]);
      }
      return this;
    }

    // appendNegatedClass() append the negation of the class |x| to this
    // CharClass.  It assumes |x| is clean.  Does not mutate |x|.
    appendNegatedClass(x) {
      let nextLo = 0;
      for (let i = 0; i < x.length; i += 2) {
        const lo = x[i];
        const hi = x[i + 1];
        if (nextLo <= lo - 1) {
          this.appendRange(nextLo, lo - 1);
        }
        nextLo = hi + 1;
      }
      if (nextLo <= Unicode.MAX_RUNE) {
        this.appendRange(nextLo, Unicode.MAX_RUNE);
      }
      return this;
    }

    // appendTable() appends the Unicode range table |table| to this CharClass.
    // Does not mutate |table|.
    appendTable(table) {
      for (let triple of table) {
        const lo = triple[0];
        const hi = triple[1];
        const stride = triple[2];
        if (stride === 1) {
          this.appendRange(lo, hi);
          continue;
        }
        for (let c = lo; c <= hi; c += stride) {
          this.appendRange(c, c);
        }
      }
      return this;
    }

    // appendNegatedTable() returns the result of appending the negation of range
    // table |table| to this CharClass.  Does not mutate |table|.
    appendNegatedTable(table) {
      let nextLo = 0;
      for (let triple of table) {
        const lo = triple[0];
        const hi = triple[1];
        const stride = triple[2];
        if (stride === 1) {
          if (nextLo <= lo - 1) {
            this.appendRange(nextLo, lo - 1);
          }
          nextLo = hi + 1;
          continue;
        }
        for (let c = lo; c <= hi; c += stride) {
          if (nextLo <= c - 1) {
            this.appendRange(nextLo, c - 1);
          }
          nextLo = c + 1;
        }
      }
      if (nextLo <= Unicode.MAX_RUNE) {
        this.appendRange(nextLo, Unicode.MAX_RUNE);
      }
      return this;
    }

    // appendTableWithSign() calls append{,Negated}Table depending on sign.
    // Does not mutate |table|.
    appendTableWithSign(table, sign) {
      return sign < 0 ? this.appendNegatedTable(table) : this.appendTable(table);
    }

    // negateClass() negates this CharClass, which must already be clean.
    negateClass() {
      let nextLo = 0; // lo end of next class to add
      let w = 0; // write index
      for (let i = 0; i < this.len; i += 2) {
        const lo = this.r[i];
        const hi = this.r[i + 1];
        if (nextLo <= lo - 1) {
          this.r[w] = nextLo;
          this.r[w + 1] = lo - 1;
          w += 2;
        }
        nextLo = hi + 1;
      }
      this.len = w;
      if (nextLo <= Unicode.MAX_RUNE) {
        this.r[this.len++] = nextLo;
        this.r[this.len++] = Unicode.MAX_RUNE;
      }
      return this;
    }

    // appendClassWithSign() calls appendClass() if sign is +1 or
    // appendNegatedClass if sign is -1.  Does not mutate |x|.
    appendClassWithSign(x, sign) {
      return sign < 0 ? this.appendNegatedClass(x) : this.appendClass(x);
    }

    // appendGroup() appends CharGroup |g| to this CharClass, folding iff
    // |foldCase|.  Does not mutate |g|.
    appendGroup(g, foldCase) {
      let cls = g.cls;
      if (foldCase) {
        cls = new CharClass().appendFoldedClass(cls).cleanClass().toArray();
      }
      return this.appendClassWithSign(cls, g.sign);
    }
    toString() {
      return CharClass.charClassToString(this.r, this.len);
    }
  }

  class Pair {
    static of(first, second) {
      return new Pair(first, second);
    }
    constructor(first, second) {
      this.first = first;
      this.second = second;
    }
  }

  // StringIterator: a stream of runes with an opaque cursor, permitting
  // rewinding.  The units of the cursor are not specified beyond the
  // fact that ASCII characters are single width.  (Cursor positions
  // could be UTF-8 byte indices, UTF-16 code indices or rune indices.)
  //
  // In particular, be careful with:
  // - skip: only use this to advance over ASCII characters
  //   since these always have a width of 1.
  // - skipString: only use this to advance over strings which are
  //   known to be at the current position, e.g. due to prior call to
  //   lookingAt().
  // Only use pop() to advance over possibly non-ASCII runes.
  class StringIterator {
    constructor(str) {
      this.str = str;
      this.position = 0;
    }

    // Returns the cursor position.  Do not interpret the result!
    pos() {
      return this.position;
    }

    // Resets the cursor position to a previous value returned by pos().
    rewindTo(pos) {
      this.position = pos;
    }

    // Returns true unless the stream is exhausted.
    more() {
      return this.position < this.str.length;
    }

    // Returns the rune at the cursor position.
    // Precondition: |more()|.
    peek() {
      return this.str.codePointAt(this.position);
    }

    // Advances the cursor by |n| positions, which must be ASCII runes.
    //
    // (In practise, this is only ever used to skip over regexp
    // metacharacters that are ASCII, so there is no numeric difference
    // between indices into  UTF-8 bytes, UTF-16 codes and runes.)
    skip(n) {
      this.position += n;
    }

    // Advances the cursor by the number of cursor positions in |s|.
    skipString(s) {
      this.position += s.length;
    }

    // Returns the rune at the cursor position, and advances the cursor
    // past it.  Precondition: |more()|.
    pop() {
      const r = this.str.codePointAt(this.position);
      this.position += Utils.charCount(r);
      return r;
    }
    lookingAt(s) {
      return this.rest().startsWith(s);
    }

    // Returns the rest of the pattern as a Java UTF-16 string.
    rest() {
      return this.str.substring(this.position);
    }

    // Returns the substring from |beforePos| to the current position.
    // |beforePos| must have been previously returned by |pos()|.
    from(beforePos) {
      return this.str.substring(beforePos, this.position);
    }
    toString() {
      return this.rest();
    }
  }
  /**
   * A parser of regular expression patterns.
   *
   * The only public entry point is {@link #parse(String pattern, int flags)}.
   */
  class Parser {
    // Unexpected error
    static ERR_INTERNAL_ERROR = 'regexp/syntax: internal error';

    // Parse errors
    static ERR_INVALID_CHAR_RANGE = 'invalid character class range';
    static ERR_INVALID_ESCAPE = 'invalid escape sequence';
    static ERR_INVALID_NAMED_CAPTURE = 'invalid named capture';
    static ERR_INVALID_PERL_OP = 'invalid or unsupported Perl syntax';
    static ERR_INVALID_REPEAT_OP = 'invalid nested repetition operator';
    static ERR_INVALID_REPEAT_SIZE = 'invalid repeat count';
    static ERR_MISSING_BRACKET = 'missing closing ]';
    static ERR_MISSING_PAREN = 'missing closing )';
    static ERR_MISSING_REPEAT_ARGUMENT = 'missing argument to repetition operator';
    static ERR_TRAILING_BACKSLASH = 'trailing backslash at end of expression';
    static ERR_DUPLICATE_NAMED_CAPTURE = 'duplicate capture group name';

    // RangeTables are represented as int[][], a list of triples (start, end,
    // stride).
    static ANY_TABLE() {
      return [[0, Unicode.MAX_RUNE, 1]];
    }

    // unicodeTable() returns the Unicode RangeTable identified by name
    // and the table of additional fold-equivalent code points.
    // Returns null if |name| does not identify a Unicode character range.
    static unicodeTable(name) {
      if (name === 'Any') {
        return Pair.of(Parser.ANY_TABLE(), Parser.ANY_TABLE());
      }
      if (UnicodeTables.CATEGORIES.has(name)) {
        return Pair.of(UnicodeTables.CATEGORIES.get(name), UnicodeTables.FOLD_CATEGORIES.get(name));
      }
      if (UnicodeTables.SCRIPTS.has(name)) {
        return Pair.of(UnicodeTables.SCRIPTS.get(name), UnicodeTables.FOLD_SCRIPT.get(name));
      }
      return null;
    }

    // minFoldRune returns the minimum rune fold-equivalent to r.
    static minFoldRune(r) {
      if (r < Unicode.MIN_FOLD || r > Unicode.MAX_FOLD) {
        return r;
      }
      let min = r;
      const r0 = r;
      for (r = Unicode.simpleFold(r); r !== r0; r = Unicode.simpleFold(r)) {
        if (min > r) {
          min = r;
        }
      }
      return min;
    }

    // leadingRegexp returns the leading regexp that re begins with.
    // The regexp refers to storage in re or its children.
    static leadingRegexp(re) {
      if (re.op === Regexp.Op.EMPTY_MATCH) {
        return null;
      }
      if (re.op === Regexp.Op.CONCAT && re.subs.length > 0) {
        const sub = re.subs[0];
        if (sub.op === Regexp.Op.EMPTY_MATCH) {
          return null;
        }
        return sub;
      }
      return re;
    }
    static literalRegexp(s, flags) {
      const re = new Regexp(Regexp.Op.LITERAL);
      re.flags = flags;
      re.runes = Utils.stringToRunes(s);
      return re;
    }
    /**
     * Parse regular expression pattern {@code pattern} with mode flags {@code flags}.
     * @param {string} pattern
     * @param {number} flags
     */
    static parse(pattern, flags) {
      return new Parser(pattern, flags).parseInternal();
    }

    // parseRepeat parses {min} (max=min) or {min,} (max=-1) or {min,max}.
    // If |t| is not of that form, it returns -1.
    // If |t| has the right form but the values are negative or too big,
    // it returns -2.
    // On success, returns a nonnegative number encoding min/max in the
    // high/low signed halfwords of the result.  (Note: min >= 0; max may
    // be -1.)
    //
    // On success, advances |t| beyond the repeat; otherwise |t.pos()| is
    // undefined.
    static parseRepeat(t) {
      const start = t.pos();
      if (!t.more() || !t.lookingAt('{')) {
        return -1;
      }
      t.skip(1);
      const min = Parser.parseInt(t);
      if (min === -1) {
        return -1;
      }
      if (!t.more()) {
        return -1;
      }
      let max;
      if (!t.lookingAt(',')) {
        max = min;
      } else {
        t.skip(1);
        if (!t.more()) {
          return -1;
        }
        if (t.lookingAt('}')) {
          max = -1;
        } else if ((max = Parser.parseInt(t)) === -1) {
          return -1;
        }
      }
      if (!t.more() || !t.lookingAt('}')) {
        return -1;
      }
      t.skip(1);
      if (min < 0 || min > 1000 || max === -2 || max > 1000 || max >= 0 && min > max) {
        throw new RE2JSSyntaxException(Parser.ERR_INVALID_REPEAT_SIZE, t.from(start));
      }
      return min << 16 | max & Unicode.MAX_BMP;
    }

    // isValidCaptureName reports whether name
    // is a valid capture name: [A-Za-z0-9_]+.
    // PCRE limits names to 32 bytes.
    // Python rejects names starting with digits.
    // We don't enforce either of those.
    static isValidCaptureName(name) {
      if (name.length === 0) {
        return false;
      }
      for (let i = 0; i < name.length; i++) {
        const c = name.codePointAt(i);
        if (c !== Codepoint.CODES.get('_') && !Utils.isalnum(c)) {
          return false;
        }
      }
      return true;
    }

    // parseInt parses a nonnegative decimal integer.
    // -1 => bad format.  -2 => format ok, but integer overflow.
    static parseInt(t) {
      const start = t.pos();
      while (t.more() && t.peek() >= Codepoint.CODES.get('0') && t.peek() <= Codepoint.CODES.get('9')) {
        t.skip(1);
      }
      const n = t.from(start);
      if (n.length === 0 || n.length > 1 && n.codePointAt(0) === Codepoint.CODES.get('0')) {
        return -1;
      }
      if (n.length > 8) {
        return -2;
      }
      return parseFloat(n, 10);
    }

    // can this be represented as a character class?
    // single-rune literal string, char class, ., and .|\n.
    static isCharClass(re) {
      return re.op === Regexp.Op.LITERAL && re.runes.length === 1 || re.op === Regexp.Op.CHAR_CLASS || re.op === Regexp.Op.ANY_CHAR_NOT_NL || re.op === Regexp.Op.ANY_CHAR;
    }

    // does re match r?
    static matchRune(re, r) {
      switch (re.op) {
        case Regexp.Op.LITERAL:
          return re.runes.length === 1 && re.runes[0] === r;
        case Regexp.Op.CHAR_CLASS:
          for (let i = 0; i < re.runes.length; i += 2) {
            if (re.runes[i] <= r && r <= re.runes[i + 1]) {
              return true;
            }
          }
          return false;
        case Regexp.Op.ANY_CHAR_NOT_NL:
          return r !== Codepoint.CODES.get('\n');
        case Regexp.Op.ANY_CHAR:
          return true;
      }
      return false;
    }

    // mergeCharClass makes dst = dst|src.
    // The caller must ensure that dst.Op >= src.Op,
    // to reduce the amount of copying.
    static mergeCharClass(dst, src) {
      switch (dst.op) {
        case Regexp.Op.ANY_CHAR:
          break;
        case Regexp.Op.ANY_CHAR_NOT_NL:
          if (Parser.matchRune(src, Codepoint.CODES.get('\n'))) {
            dst.op = Regexp.Op.ANY_CHAR;
          }
          break;
        case Regexp.Op.CHAR_CLASS:
          if (src.op === Regexp.Op.LITERAL) {
            dst.runes = new CharClass(dst.runes).appendLiteral(src.runes[0], src.flags).toArray();
          } else {
            dst.runes = new CharClass(dst.runes).appendClass(src.runes).toArray();
          }
          break;
        case Regexp.Op.LITERAL:
          if (src.runes[0] === dst.runes[0] && src.flags === dst.flags) {
            break;
          }
          dst.op = Regexp.Op.CHAR_CLASS;
          dst.runes = new CharClass().appendLiteral(dst.runes[0], dst.flags).appendLiteral(src.runes[0], src.flags).toArray();
          break;
      }
    }

    // parseEscape parses an escape sequence at the beginning of s
    // and returns the rune.
    // Pre: t at '\\'.  Post: after escape.
    static parseEscape(t) {
      const startPos = t.pos();
      t.skip(1); // '\\'
      if (!t.more()) {
        throw new RE2JSSyntaxException(Parser.ERR_TRAILING_BACKSLASH);
      }
      let c = t.pop();
      bigswitch: switch (c) {
        case Codepoint.CODES.get('1'):
        case Codepoint.CODES.get('2'):
        case Codepoint.CODES.get('3'):
        case Codepoint.CODES.get('4'):
        case Codepoint.CODES.get('5'):
        case Codepoint.CODES.get('6'):
        case Codepoint.CODES.get('7'):
          {
            if (!t.more() || t.peek() < Codepoint.CODES.get('0') || t.peek() > Codepoint.CODES.get('7')) {
              break;
            }
          }
        // eslint-disable-next-line no-fallthrough
        case Codepoint.CODES.get('0'):
          {
            let r = c - Codepoint.CODES.get('0');
            for (let i = 1; i < 3; i++) {
              if (!t.more() || t.peek() < Codepoint.CODES.get('0') || t.peek() > Codepoint.CODES.get('7')) {
                break;
              }
              r = r * 8 + t.peek() - Codepoint.CODES.get('0');
              t.skip(1);
            }
            return r;
          }
        case Codepoint.CODES.get('x'):
          {
            if (!t.more()) {
              break;
            }
            c = t.pop();
            if (c === Codepoint.CODES.get('{')) {
              let nhex = 0;
              let r = 0;
              // eslint-disable-next-line no-constant-condition
              while (true) {
                if (!t.more()) {
                  break bigswitch;
                }
                c = t.pop();
                if (c === Codepoint.CODES.get('}')) {
                  break;
                }
                const v = Utils.unhex(c);
                if (v < 0) {
                  break bigswitch;
                }
                r = r * 16 + v;
                if (r > Unicode.MAX_RUNE) {
                  break bigswitch;
                }
                nhex++;
              }
              if (nhex === 0) {
                break bigswitch;
              }
              return r;
            }
            const x = Utils.unhex(c);
            if (!t.more()) {
              break;
            }
            c = t.pop();
            const y = Utils.unhex(c);
            if (x < 0 || y < 0) {
              break;
            }
            return x * 16 + y;
          }
        case Codepoint.CODES.get('a'):
          return Codepoint.CODES.get('\x07');
        case Codepoint.CODES.get('f'):
          return Codepoint.CODES.get('\f');
        case Codepoint.CODES.get('n'):
          return Codepoint.CODES.get('\n');
        case Codepoint.CODES.get('r'):
          return Codepoint.CODES.get('\r');
        case Codepoint.CODES.get('t'):
          return Codepoint.CODES.get('\t');
        case Codepoint.CODES.get('v'):
          return Codepoint.CODES.get('\v');
        default:
          if (!Utils.isalnum(c)) {
            return c;
          }
          break;
      }
      throw new RE2JSSyntaxException(Parser.ERR_INVALID_ESCAPE, t.from(startPos));
    }

    // parseClassChar parses a character class character and returns it.
    // wholeClassPos is the position of the start of the entire class "[...".
    // Pre: t at class char; Post: t after it.
    static parseClassChar(t, wholeClassPos) {
      if (!t.more()) {
        throw new RE2JSSyntaxException(Parser.ERR_MISSING_BRACKET, t.from(wholeClassPos));
      }
      if (t.lookingAt('\\')) {
        return Parser.parseEscape(t);
      }
      return t.pop();
    }
    static concatRunes(x, y) {
      return [...x, ...y];
    }
    constructor(wholeRegexp, flags = 0) {
      this.wholeRegexp = wholeRegexp;
      // Flags control the behavior of the parser and record information about
      // regexp context.
      this.flags = flags;
      // number of capturing groups seen
      this.numCap = 0;
      this.namedGroups = {};
      // Stack of parsed expressions.
      this.stack = [];
      this.free = null;
    }

    // Allocate a Regexp, from the free list if possible.
    newRegexp(op) {
      let re = this.free;
      if (re !== null && re.subs !== null && re.subs.length > 0) {
        this.free = re.subs[0];
        re.reinit();
        re.op = op;
      } else {
        re = new Regexp(op);
      }
      return re;
    }
    reuse(re) {
      if (re.subs !== null && re.subs.length > 0) {
        re.subs[0] = this.free;
      }
      this.free = re;
    }

    // Parse stack manipulation.

    pop() {
      return this.stack.pop();
    }
    popToPseudo() {
      const n = this.stack.length;
      let i = n;
      while (i > 0 && !Regexp.isPseudoOp(this.stack[i - 1].op)) {
        i--;
      }
      const r = this.stack.slice(i, n);
      this.stack = this.stack.slice(0, i);
      return r;
    }

    // push pushes the regexp re onto the parse stack and returns the regexp.
    // Returns null for a CHAR_CLASS that can be merged with the top-of-stack.
    push(re) {
      if (re.op === Regexp.Op.CHAR_CLASS && re.runes.length === 2 && re.runes[0] === re.runes[1]) {
        if (this.maybeConcat(re.runes[0], this.flags & ~RE2Flags.FOLD_CASE)) {
          return null;
        }
        re.op = Regexp.Op.LITERAL;
        re.runes = [re.runes[0]];
        re.flags = this.flags & ~RE2Flags.FOLD_CASE;
      } else if (re.op === Regexp.Op.CHAR_CLASS && re.runes.length === 4 && re.runes[0] === re.runes[1] && re.runes[2] === re.runes[3] && Unicode.simpleFold(re.runes[0]) === re.runes[2] && Unicode.simpleFold(re.runes[2]) === re.runes[0] || re.op === Regexp.Op.CHAR_CLASS && re.runes.length === 2 && re.runes[0] + 1 === re.runes[1] && Unicode.simpleFold(re.runes[0]) === re.runes[1] && Unicode.simpleFold(re.runes[1]) === re.runes[0]) {
        // Case-insensitive rune like [Aa] or [Δδ].
        if (this.maybeConcat(re.runes[0], this.flags | RE2Flags.FOLD_CASE)) {
          return null;
        }
        // Rewrite as (case-insensitive) literal.
        re.op = Regexp.Op.LITERAL;
        re.runes = [re.runes[0]];
        re.flags = this.flags | RE2Flags.FOLD_CASE;
      } else {
        // Incremental concatenation.
        this.maybeConcat(-1, 0);
      }
      this.stack.push(re);
      return re;
    }

    // maybeConcat implements incremental concatenation
    // of literal runes into string nodes.  The parser calls this
    // before each push, so only the top fragment of the stack
    // might need processing.  Since this is called before a push,
    // the topmost literal is no longer subject to operators like *
    // (Otherwise ab* would turn into (ab)*.)
    // If (r >= 0 and there's a node left over, maybeConcat uses it
    // to push r with the given flags.
    // maybeConcat reports whether r was pushed.
    maybeConcat(r, flags) {
      const n = this.stack.length;
      if (n < 2) {
        return false;
      }
      const re1 = this.stack[n - 1];
      const re2 = this.stack[n - 2];
      if (re1.op !== Regexp.Op.LITERAL || re2.op !== Regexp.Op.LITERAL || (re1.flags & RE2Flags.FOLD_CASE) !== (re2.flags & RE2Flags.FOLD_CASE)) {
        return false;
      }
      // Push re1 into re2.
      re2.runes = Parser.concatRunes(re2.runes, re1.runes);
      // Reuse re1 if possible.
      if (r >= 0) {
        re1.runes = [r];
        re1.flags = flags;
        return true;
      }
      this.pop();
      this.reuse(re1);
      return false; // did not push r
    }

    // newLiteral returns a new LITERAL Regexp with the given flags
    newLiteral(r, flags) {
      const re = this.newRegexp(Regexp.Op.LITERAL);
      re.flags = flags;
      if ((flags & RE2Flags.FOLD_CASE) !== 0) {
        r = Parser.minFoldRune(r);
      }
      re.runes = [r];
      return re;
    }

    // literal pushes a literal regexp for the rune r on the stack
    // and returns that regexp.
    literal(r) {
      this.push(this.newLiteral(r, this.flags));
    }

    // op pushes a regexp with the given op onto the stack
    // and returns that regexp.
    op(op) {
      const re = this.newRegexp(op);
      re.flags = this.flags;
      return this.push(re);
    }

    // repeat replaces the top stack element with itself repeated according to
    // op, min, max.  beforePos is the start position of the repetition operator.
    // Pre: t is positioned after the initial repetition operator.
    // Post: t advances past an optional perl-mode '?', or stays put.
    //       Or, it fails with RE2JSSyntaxException.
    repeat(op, min, max, beforePos, t, lastRepeatPos) {
      let flags = this.flags;
      if ((flags & RE2Flags.PERL_X) !== 0) {
        if (t.more() && t.lookingAt('?')) {
          t.skip(1);
          flags ^= RE2Flags.NON_GREEDY;
        }
        if (lastRepeatPos !== -1) {
          // In Perl it is not allowed to stack repetition operators:
          // a** is a syntax error, not a doubled star, and a++ means
          // something else entirely, which we don't support!
          throw new RE2JSSyntaxException(Parser.ERR_INVALID_REPEAT_OP, t.from(lastRepeatPos));
        }
      }
      const n = this.stack.length;
      if (n === 0) {
        throw new RE2JSSyntaxException(Parser.ERR_MISSING_REPEAT_ARGUMENT, t.from(beforePos));
      }
      const sub = this.stack[n - 1];
      if (Regexp.isPseudoOp(sub.op)) {
        throw new RE2JSSyntaxException(Parser.ERR_MISSING_REPEAT_ARGUMENT, t.from(beforePos));
      }
      const re = this.newRegexp(op);
      re.min = min;
      re.max = max;
      re.flags = flags;
      re.subs = [sub];
      this.stack[n - 1] = re;
    }

    // concat replaces the top of the stack (above the topmost '|' or '(') with
    // its concatenation.
    concat() {
      this.maybeConcat(-1, 0);
      const subs = this.popToPseudo();
      if (subs.length === 0) {
        return this.push(this.newRegexp(Regexp.Op.EMPTY_MATCH));
      }
      return this.push(this.collapse(subs, Regexp.Op.CONCAT));
    }

    // alternate replaces the top of the stack (above the topmost '(') with its
    // alternation.
    alternate() {
      // Scan down to find pseudo-operator (.
      // There are no | above (.
      const subs = this.popToPseudo();
      // Make sure top class is clean.
      // All the others already are (see swapVerticalBar).
      if (subs.length > 0) {
        this.cleanAlt(subs[subs.length - 1]);
      }
      // Empty alternate is special case
      // (shouldn't happen but easy to handle).
      if (subs.length === 0) {
        return this.push(this.newRegexp(Regexp.Op.NO_MATCH));
      }
      return this.push(this.collapse(subs, Regexp.Op.ALTERNATE));
    }

    // cleanAlt cleans re for eventual inclusion in an alternation.
    cleanAlt(re) {
      if (re.op === Regexp.Op.CHAR_CLASS) {
        re.runes = new CharClass(re.runes).cleanClass().toArray();
        if (re.runes.length === 2 && re.runes[0] === 0 && re.runes[1] === Unicode.MAX_RUNE) {
          re.runes = null;
          re.op = Regexp.Op.ANY_CHAR;
        } else if (re.runes.length === 4 && re.runes[0] === 0 && re.runes[1] === Codepoint.CODES.get('\n') - 1 && re.runes[2] === Codepoint.CODES.get('\n') + 1 && re.runes[3] === Unicode.MAX_RUNE) {
          re.runes = null;
          re.op = Regexp.Op.ANY_CHAR_NOT_NL;
        }
      }
    }

    // collapse returns the result of applying op to subs[start:end].
    // If (sub contains op nodes, they all get hoisted up
    // so that there is never a concat of a concat or an
    // alternate of an alternate.
    collapse(subs, op) {
      if (subs.length === 1) {
        return subs[0];
      }
      // Concatenate subs iff op is same.
      // Compute length in first pass.
      let len = 0;
      for (let sub of subs) {
        len += sub.op === op ? sub.subs.length : 1;
      }
      let newsubs = new Array(len).fill(null);
      let i = 0;
      for (let sub of subs) {
        if (sub.op === op) {
          newsubs.splice(i, sub.subs.length, ...sub.subs);
          i += sub.subs.length;
          this.reuse(sub);
        } else {
          newsubs[i++] = sub;
        }
      }
      let re = this.newRegexp(op);
      re.subs = newsubs;
      if (op === Regexp.Op.ALTERNATE) {
        // re.subs = this.factor(re.subs, re.flags)
        re.subs = this.factor(re.subs);
        if (re.subs.length === 1) {
          const old = re;
          re = re.subs[0];
          this.reuse(old);
        }
      }
      return re;
    }

    // factor factors common prefixes from the alternation list sub.  It
    // returns a replacement list that reuses the same storage and frees
    // (passes to p.reuse) any removed *Regexps.
    //
    // For example,
    //     ABC|ABD|AEF|BCX|BCY
    // simplifies by literal prefix extraction to
    //     A(B(C|D)|EF)|BC(X|Y)
    // which simplifies by character class introduction to
    //     A(B[CD]|EF)|BC[XY]
    //
    factor(array) {
      if (array.length < 2) {
        return array;
      }
      // The following code is subtle, because it's a literal JS
      // translation of code that makes clever use of Go "slices".
      // A slice is a triple (array, offset, length), and the Go
      // implementation uses two slices, |sub| and |out| backed by the
      // same array.  In JS, we have to be explicit about all of these
      // variables, so:
      //
      // Go    JS
      // sub   (array, s, lensub)
      // out   (array, 0, lenout)   // (always a prefix of |array|)
      //
      // In the comments we'll use the logical notation of go slices, e.g. sub[i]
      // even though the JS code will read array[s + i].

      let s = 0; // offset of first |sub| within array.
      let lensub = array.length; // = len(sub)
      let lenout = 0; // = len(out)
      // Round 1: Factor out common literal prefixes.
      // Note: (str, strlen) and (istr, istrlen) are like Go slices
      // onto a prefix of some Regexp's runes array (hence offset=0).
      let str = null;
      let strlen = 0;
      let strflags = 0;
      let start = 0;
      for (let i = 0; i <= lensub; i++) {
        // Invariant: the Regexps that were in sub[0:start] have been
        // used or marked for reuse, and the slice space has been reused
        // for out (len <= start).
        //
        // Invariant: sub[start:i] consists of regexps that all begin
        // with str as modified by strflags.
        let istr = null;
        let istrlen = 0;
        let iflags = 0;
        if (i < lensub) {
          // NB, we inlined Go's leadingString() since Java has no pair return.
          let re = array[s + i];
          if (re.op === Regexp.Op.CONCAT && re.subs.length > 0) {
            re = re.subs[0];
          }
          if (re.op === Regexp.Op.LITERAL) {
            istr = re.runes;
            istrlen = re.runes.length;
            iflags = re.flags & RE2Flags.FOLD_CASE;
          }
          // istr is the leading literal string that re begins with.
          // The string refers to storage in re or its children.
          if (iflags === strflags) {
            let same = 0;
            while (same < strlen && same < istrlen && str[same] === istr[same]) {
              same++;
            }
            if (same > 0) {
              // Matches at least one rune in current range.
              // Keep going around.
              strlen = same;
              continue;
            }
          }
        }
        // Found end of a run with common leading literal string:
        // sub[start:i] all begin with str[0:strlen], but sub[i]
        // does not even begin with str[0].
        //
        // Factor out common string and append factored expression to out.
        if (i === start) ; else if (i === start + 1) {
          // Just one: don't bother factoring.
          array[lenout++] = array[s + start];
        } else {
          // Construct factored form: prefix(suffix1|suffix2|...)
          const prefix = this.newRegexp(Regexp.Op.LITERAL);
          prefix.flags = strflags;
          prefix.runes = str.slice(0, strlen);
          for (let j = start; j < i; j++) {
            array[s + j] = this.removeLeadingString(array[s + j], strlen);
          }
          // Recurse.
          const suffix = this.collapse(array.slice(s + start, s + i), Regexp.Op.ALTERNATE);
          const re = this.newRegexp(Regexp.Op.CONCAT);
          re.subs = [prefix, suffix];
          array[lenout++] = re;
        }
        // Prepare for next iteration.
        start = i;
        str = istr;
        strlen = istrlen;
        strflags = iflags;
      }
      // In Go: sub = out
      lensub = lenout;
      s = 0;
      // Round 2: Factor out common complex prefixes,
      // just the first piece of each concatenation,
      // whatever it is.  This is good enough a lot of the time.
      start = 0;
      lenout = 0;
      let first = null;
      for (let i = 0; i <= lensub; i++) {
        // Invariant: the Regexps that were in sub[0:start] have been
        // used or marked for reuse, and the slice space has been reused
        // for out (lenout <= start).
        //
        // Invariant: sub[start:i] consists of regexps that all begin with
        // ifirst.
        let ifirst = null;
        if (i < lensub) {
          ifirst = Parser.leadingRegexp(array[s + i]);
          if (first !== null && first.equals(ifirst) && (Parser.isCharClass(first) || first.op === Regexp.Op.REPEAT && first.min === first.max && Parser.isCharClass(first.subs[0]))) {
            continue;
          }
        }
        // Found end of a run with common leading regexp:
        // sub[start:i] all begin with first but sub[i] does not.
        //
        // Factor out common regexp and append factored expression to out.
        if (i === start) ; else if (i === start + 1) {
          // Just one: don't bother factoring.
          array[lenout++] = array[s + start];
        } else {
          // Construct factored form: prefix(suffix1|suffix2|...)
          const prefix = first;
          for (let j = start; j < i; j++) {
            const reuse = j !== start; // prefix came from sub[start]
            array[s + j] = this.removeLeadingRegexp(array[s + j], reuse);
          }
          // recurse
          const suffix = this.collapse(array.slice(s + start, s + i), Regexp.Op.ALTERNATE);
          const re = this.newRegexp(Regexp.Op.CONCAT);
          re.subs = [prefix, suffix];
          array[lenout++] = re;
        }
        // Prepare for next iteration.
        start = i;
        first = ifirst;
      }
      // In Go: sub = out
      lensub = lenout;
      s = 0;
      // Round 3: Collapse runs of single literals into character classes.
      start = 0;
      lenout = 0;
      for (let i = 0; i <= lensub; i++) {
        // Invariant: the Regexps that were in sub[0:start] have been
        // used or marked for reuse, and the slice space has been reused
        // for out (lenout <= start).
        //
        // Invariant: sub[start:i] consists of regexps that are either
        // literal runes or character classes.
        if (i < lensub && Parser.isCharClass(array[s + i])) {
          continue;
        }
        // sub[i] is not a char or char class;
        // emit char class for sub[start:i]...
        if (i === start) ; else if (i === start + 1) {
          // Just one: don't bother factoring.
          array[lenout++] = array[s + start];
        } else {
          // Make new char class.
          // Start with most complex regexp in sub[start].
          let max = start;
          for (let j = start + 1; j < i; j++) {
            const subMax = array[s + max];
            const subJ = array[s + j];
            if (subMax.op < subJ.op || subMax.op === subJ.op && (subMax.runes !== null ? subMax.runes.length : 0) < (subJ.runes !== null ? subJ.runes.length : 0)) {
              max = j;
            }
          }
          // swap sub[start], sub[max].
          const tmp = array[s + start];
          array[s + start] = array[s + max];
          array[s + max] = tmp;
          for (let j = start + 1; j < i; j++) {
            Parser.mergeCharClass(array[s + start], array[s + j]);
            this.reuse(array[s + j]);
          }
          this.cleanAlt(array[s + start]);
          array[lenout++] = array[s + start];
        }
        // ... and then emit sub[i].
        if (i < lensub) {
          array[lenout++] = array[s + i];
        }
        start = i + 1;
      }
      // In Go: sub = out
      lensub = lenout;
      s = 0;
      // Round 4: Collapse runs of empty matches into a single empty match.
      start = 0;
      lenout = 0;
      for (let i = 0; i < lensub; ++i) {
        if (i + 1 < lensub && array[s + i].op === Regexp.Op.EMPTY_MATCH && array[s + i + 1].op === Regexp.Op.EMPTY_MATCH) {
          continue;
        }
        array[lenout++] = array[s + i];
      }
      // In Go: sub = out
      lensub = lenout;
      s = 0;
      return array.slice(s, lensub);
    }

    // removeLeadingString removes the first n leading runes
    // from the beginning of re.  It returns the replacement for re.
    removeLeadingString(re, n) {
      if (re.op === Regexp.Op.CONCAT && re.subs.length > 0) {
        // Removing a leading string in a concatenation
        // might simplify the concatenation.
        const sub = this.removeLeadingString(re.subs[0], n);
        re.subs[0] = sub;
        if (sub.op === Regexp.Op.EMPTY_MATCH) {
          this.reuse(sub);
          switch (re.subs.length) {
            case 0:
            case 1:
              // Impossible but handle.
              re.op = Regexp.Op.EMPTY_MATCH;
              re.subs = null;
              break;
            case 2:
              {
                const old = re;
                re = re.subs[1];
                this.reuse(old);
                break;
              }
            default:
              re.subs = re.subs.slice(1, re.subs.length);
              break;
          }
        }
        return re;
      }
      if (re.op === Regexp.Op.LITERAL) {
        re.runes = re.runes.slice(n, re.runes.length);
        if (re.runes.length === 0) {
          re.op = Regexp.Op.EMPTY_MATCH;
        }
      }
      return re;
    }

    // removeLeadingRegexp removes the leading regexp in re.
    // It returns the replacement for re.
    // If reuse is true, it passes the removed regexp (if no longer needed) to
    // reuse.
    removeLeadingRegexp(re, reuse) {
      if (re.op === Regexp.Op.CONCAT && re.subs.length > 0) {
        if (reuse) {
          this.reuse(re.subs[0]);
        }
        re.subs = re.subs.slice(1, re.subs.length);
        switch (re.subs.length) {
          case 0:
            {
              re.op = Regexp.Op.EMPTY_MATCH;
              re.subs = Regexp.emptySubs();
              break;
            }
          case 1:
            {
              const old = re;
              re = re.subs[0];
              this.reuse(old);
              break;
            }
        }
        return re;
      }
      if (reuse) {
        this.reuse(re);
      }
      return this.newRegexp(Regexp.Op.EMPTY_MATCH);
    }
    parseInternal() {
      if ((this.flags & RE2Flags.LITERAL) !== 0) {
        // Trivial parser for literal string.
        return Parser.literalRegexp(this.wholeRegexp, this.flags);
      }
      // Otherwise, must do real work.
      let lastRepeatPos = -1;
      let min = -1;
      let max = -1;
      const t = new StringIterator(this.wholeRegexp);
      while (t.more()) {
        {
          let repeatPos = -1;
          bigswitch: switch (t.peek()) {
            case Codepoint.CODES.get('('):
              if ((this.flags & RE2Flags.PERL_X) !== 0 && t.lookingAt('(?')) {
                // Flag changes and non-capturing groups.
                this.parsePerlFlags(t);
                break;
              }
              this.op(Regexp.Op.LEFT_PAREN).cap = ++this.numCap;
              t.skip(1); // '('
              break;
            case Codepoint.CODES.get('|'):
              this.parseVerticalBar(); // '|'
              t.skip(1); // '|'
              break;
            case Codepoint.CODES.get(')'):
              this.parseRightParen();
              t.skip(1); // ')'
              break;
            case Codepoint.CODES.get('^'):
              if ((this.flags & RE2Flags.ONE_LINE) !== 0) {
                this.op(Regexp.Op.BEGIN_TEXT);
              } else {
                this.op(Regexp.Op.BEGIN_LINE);
              }
              t.skip(1); // '^'
              break;
            case Codepoint.CODES.get('$'):
              if ((this.flags & RE2Flags.ONE_LINE) !== 0) {
                this.op(Regexp.Op.END_TEXT).flags |= RE2Flags.WAS_DOLLAR;
              } else {
                this.op(Regexp.Op.END_LINE);
              }
              t.skip(1); // '$'
              break;
            case Codepoint.CODES.get('.'):
              if ((this.flags & RE2Flags.DOT_NL) !== 0) {
                this.op(Regexp.Op.ANY_CHAR);
              } else {
                this.op(Regexp.Op.ANY_CHAR_NOT_NL);
              }
              t.skip(1); // '.'
              break;
            case Codepoint.CODES.get('['):
              this.parseClass(t);
              break;
            case Codepoint.CODES.get('*'):
            case Codepoint.CODES.get('+'):
            case Codepoint.CODES.get('?'):
              {
                repeatPos = t.pos();
                let op = null;
                switch (t.pop()) {
                  case Codepoint.CODES.get('*'):
                    op = Regexp.Op.STAR;
                    break;
                  case Codepoint.CODES.get('+'):
                    op = Regexp.Op.PLUS;
                    break;
                  case Codepoint.CODES.get('?'):
                    op = Regexp.Op.QUEST;
                    break;
                }
                this.repeat(op, min, max, repeatPos, t, lastRepeatPos);
                // (min and max are now dead.)
                break;
              }
            case Codepoint.CODES.get('{'):
              {
                repeatPos = t.pos();
                const minMax = Parser.parseRepeat(t);
                if (minMax < 0) {
                  // If the repeat cannot be parsed, { is a literal.
                  t.rewindTo(repeatPos);
                  this.literal(t.pop()); // '{'
                  break;
                }
                min = minMax >> 16;
                max = (minMax & Unicode.MAX_BMP) << 16 >> 16;
                this.repeat(Regexp.Op.REPEAT, min, max, repeatPos, t, lastRepeatPos);
                break;
              }
            case Codepoint.CODES.get('\\'):
              {
                const savedPos = t.pos();
                t.skip(1); // '\\'
                if ((this.flags & RE2Flags.PERL_X) !== 0 && t.more()) {
                  const c = t.pop();
                  switch (c) {
                    case Codepoint.CODES.get('A'):
                      this.op(Regexp.Op.BEGIN_TEXT);
                      break bigswitch;
                    case Codepoint.CODES.get('b'):
                      this.op(Regexp.Op.WORD_BOUNDARY);
                      break bigswitch;
                    case Codepoint.CODES.get('B'):
                      this.op(Regexp.Op.NO_WORD_BOUNDARY);
                      break bigswitch;
                    case Codepoint.CODES.get('C'):
                      // any byte; not supported
                      throw new RE2JSSyntaxException(Parser.ERR_INVALID_ESCAPE, '\\C');
                    case Codepoint.CODES.get('Q'):
                      {
                        // \Q ... \E: the ... is always literals
                        let lit = t.rest();
                        const i = lit.indexOf('\\E');
                        if (i >= 0) {
                          lit = lit.substring(0, i);
                        }
                        t.skipString(lit);
                        t.skipString('\\E');
                        let j = 0;
                        while (j < lit.length) {
                          const codepoint = lit.codePointAt(j);
                          this.literal(codepoint);
                          j += Utils.charCount(codepoint);
                        }
                        break bigswitch;
                      }
                    case Codepoint.CODES.get('z'):
                      this.op(Regexp.Op.END_TEXT);
                      break bigswitch;
                    default:
                      t.rewindTo(savedPos);
                      break;
                  }
                }
                const re = this.newRegexp(Regexp.Op.CHAR_CLASS);
                re.flags = this.flags;
                // Look for Unicode character group like \p{Han}
                if (t.lookingAt('\\p') || t.lookingAt('\\P')) {
                  const cc = new CharClass();
                  if (this.parseUnicodeClass(t, cc)) {
                    re.runes = cc.toArray();
                    this.push(re);
                    break bigswitch;
                  }
                }
                // Perl character class escape.
                const cc = new CharClass();
                if (this.parsePerlClassEscape(t, cc)) {
                  re.runes = cc.toArray();
                  this.push(re);
                  break bigswitch;
                }
                t.rewindTo(savedPos);
                this.reuse(re);
                // Ordinary single-character escape.
                this.literal(Parser.parseEscape(t));
                break;
              }
            default:
              this.literal(t.pop());
              break;
          }
          lastRepeatPos = repeatPos;
        }
      }
      this.concat();
      if (this.swapVerticalBar()) {
        this.pop(); // pop vertical bar
      }
      this.alternate();
      const n = this.stack.length;
      if (n !== 1) {
        throw new RE2JSSyntaxException(Parser.ERR_MISSING_PAREN, this.wholeRegexp);
      }
      this.stack[0].namedGroups = this.namedGroups;
      return this.stack[0];
    }

    // parsePerlFlags parses a Perl flag setting or non-capturing group or both,
    // like (?i) or (?: or (?i:.
    // Pre: t at "(?".  Post: t after ")".
    // Sets numCap.
    parsePerlFlags(t) {
      const startPos = t.pos();
      // Check for named captures, first introduced in Python's regexp library.
      // As usual, there are three slightly different syntaxes:
      //
      //   (?P<name>expr)   the original, introduced by Python
      //   (?<name>expr)    the .NET alteration, adopted by Perl 5.10
      //   (?'name'expr)    another .NET alteration, adopted by Perl 5.10
      //
      // Perl 5.10 gave in and implemented the Python version too,
      // but they claim that the last two are the preferred forms.
      // PCRE and languages based on it (specifically, PHP and Ruby)
      // support all three as well.  EcmaScript 4 uses only the Python form.
      //
      // In both the open source world (via Code Search) and the
      // Google source tree, (?P<name>expr) and (?<name>expr) are the
      // dominant forms of named captures and both are supported.
      const s = t.rest();
      if (s.startsWith('(?P<') || s.startsWith('(?<')) {
        // Pull out name.
        const begin = s.charAt(2) === 'P' ? 4 : 3;
        const end = s.indexOf('>');
        if (end < 0) {
          throw new RE2JSSyntaxException(Parser.ERR_INVALID_NAMED_CAPTURE, s);
        }
        const name = s.substring(begin, end); // "name"
        t.skipString(name);
        t.skip(begin + 1); // "(?P<>" or "(?<>"
        if (!Parser.isValidCaptureName(name)) {
          // "(?P<name>"
          throw new RE2JSSyntaxException(Parser.ERR_INVALID_NAMED_CAPTURE, s.substring(0, end + 1)); // "(?P<name>" or "(?<name>"
        }
        // Like ordinary capture, but named.
        const re = this.op(Regexp.Op.LEFT_PAREN);
        re.cap = ++this.numCap;
        if (this.namedGroups[name]) {
          throw new RE2JSSyntaxException(Parser.ERR_DUPLICATE_NAMED_CAPTURE, name);
        }
        this.namedGroups[name] = this.numCap;
        re.name = name;
        return;
      }
      // Non-capturing group.  Might also twiddle Perl flags.
      t.skip(2); // "(?"

      let flags = this.flags;
      let sign = +1;
      let sawFlag = false;
      loop: while (t.more()) {
        {
          const c = t.pop();
          switch (c) {
            case Codepoint.CODES.get('i'):
              flags |= RE2Flags.FOLD_CASE;
              sawFlag = true;
              break;
            case Codepoint.CODES.get('m'):
              flags &= ~RE2Flags.ONE_LINE;
              sawFlag = true;
              break;
            case Codepoint.CODES.get('s'):
              flags |= RE2Flags.DOT_NL;
              sawFlag = true;
              break;
            case Codepoint.CODES.get('U'):
              flags |= RE2Flags.NON_GREEDY;
              sawFlag = true;
              break;
            // Switch to negation.
            case Codepoint.CODES.get('-'):
              if (sign < 0) {
                break loop;
              }
              sign = -1;
              // Invert flags so that | above turn into &~ and vice versa.
              // We'll invert flags again before using it below.
              flags = ~flags;
              sawFlag = false;
              break;
            // End of flags, starting group or not.
            case Codepoint.CODES.get(':'):
            case Codepoint.CODES.get(')'):
              if (sign < 0) {
                if (!sawFlag) {
                  break loop;
                }
                flags = ~flags;
              }
              if (c === Codepoint.CODES.get(':')) {
                // Open new group
                this.op(Regexp.Op.LEFT_PAREN);
              }
              this.flags = flags;
              return;
            default:
              // Flags.
              break loop;
          }
        }
      }
      throw new RE2JSSyntaxException(Parser.ERR_INVALID_PERL_OP, t.from(startPos));
    }

    // parseVerticalBar handles a | in the input.
    parseVerticalBar() {
      this.concat();
      // The concatenation we just parsed is on top of the stack.
      // If it sits above an opVerticalBar, swap it below
      // (things below an opVerticalBar become an alternation).
      // Otherwise, push a new vertical bar.
      if (!this.swapVerticalBar()) {
        this.op(Regexp.Op.VERTICAL_BAR);
      }
    }

    // If the top of the stack is an element followed by an opVerticalBar
    // swapVerticalBar swaps the two and returns true.
    // Otherwise it returns false.
    swapVerticalBar() {
      const n = this.stack.length;
      // If above and below vertical bar are literal or char class,
      // can merge into a single char class.
      if (n >= 3 && this.stack[n - 2].op === Regexp.Op.VERTICAL_BAR && Parser.isCharClass(this.stack[n - 1]) && Parser.isCharClass(this.stack[n - 3])) {
        let re1 = this.stack[n - 1];
        let re3 = this.stack[n - 3];
        // Make re3 the more complex of the two.
        if (re1.op > re3.op) {
          const tmp = re3;
          re3 = re1;
          re1 = tmp;
          this.stack[n - 3] = re3;
        }
        Parser.mergeCharClass(re3, re1);
        this.reuse(re1);
        this.pop();
        return true;
      }
      if (n >= 2) {
        const re1 = this.stack[n - 1];
        const re2 = this.stack[n - 2];
        if (re2.op === Regexp.Op.VERTICAL_BAR) {
          if (n >= 3) {
            // Now out of reach.
            // Clean opportunistically.
            this.cleanAlt(this.stack[n - 3]);
          }
          this.stack[n - 2] = re1;
          this.stack[n - 1] = re2;
          return true;
        }
      }
      return false;
    }

    // parseRightParen handles a ')' in the input.
    parseRightParen() {
      this.concat();
      if (this.swapVerticalBar()) {
        this.pop(); // pop vertical bar
      }
      this.alternate();
      const n = this.stack.length;
      if (n < 2) {
        throw new RE2JSSyntaxException(Parser.ERR_INTERNAL_ERROR, 'stack underflow');
      }
      const re1 = this.pop();
      const re2 = this.pop();
      if (re2.op !== Regexp.Op.LEFT_PAREN) {
        throw new RE2JSSyntaxException(Parser.ERR_MISSING_PAREN, this.wholeRegexp);
      }
      // Restore flags at time of paren.
      this.flags = re2.flags;
      if (re2.cap === 0) {
        // Just for grouping.
        this.push(re1);
      } else {
        re2.op = Regexp.Op.CAPTURE;
        re2.subs = [re1];
        this.push(re2);
      }
    }

    // parsePerlClassEscape parses a leading Perl character class escape like \d
    // from the beginning of |t|.  If one is present, it appends the characters
    // to cc and returns true.  The iterator is advanced past the escape
    // on success, undefined on failure, in which case false is returned.
    parsePerlClassEscape(t, cc) {
      const beforePos = t.pos();
      if ((this.flags & RE2Flags.PERL_X) === 0 || !t.more() || t.pop() !== Codepoint.CODES.get('\\') || !t.more()) {
        return false;
      }
      t.pop(); // e.g. advance past 'd' in "\\d"
      const p = t.from(beforePos);
      const g = PERL_GROUPS.has(p) ? PERL_GROUPS.get(p) : null;
      if (g === null) {
        return false;
      }
      cc.appendGroup(g, (this.flags & RE2Flags.FOLD_CASE) !== 0);
      return true;
    }

    // parseNamedClass parses a leading POSIX named character class like
    // [:alnum:] from the beginning of t.  If one is present, it appends the
    // characters to cc, advances the iterator, and returns true.
    // Pre: t at "[:".  Post: t after ":]".
    // On failure (no class of than name), throws RE2JSSyntaxException.
    // On misparse, returns false; t.pos() is undefined.
    parseNamedClass(t, cc) {
      // (Go precondition check deleted.)
      const cls = t.rest();
      const i = cls.indexOf(':]');
      if (i < 0) {
        return false;
      }
      const name = cls.substring(0, i + 2); // "[:alnum:]"
      t.skipString(name);
      const g = POSIX_GROUPS.has(name) ? POSIX_GROUPS.get(name) : null;
      if (g === null) {
        throw new RE2JSSyntaxException(Parser.ERR_INVALID_CHAR_RANGE, name);
      }
      cc.appendGroup(g, (this.flags & RE2Flags.FOLD_CASE) !== 0);
      return true;
    }

    // parseUnicodeClass() parses a leading Unicode character class like \p{Han}
    // from the beginning of t.  If one is present, it appends the characters to
    // to |cc|, advances |t| and returns true.
    //
    // Returns false if such a pattern is not present or UNICODE_GROUPS
    // flag is not enabled; |t.pos()| is not advanced in this case.
    // Indicates error by throwing RE2JSSyntaxException.
    parseUnicodeClass(t, cc) {
      const startPos = t.pos();
      if ((this.flags & RE2Flags.UNICODE_GROUPS) === 0 || !t.lookingAt('\\p') && !t.lookingAt('\\P')) {
        return false;
      }
      t.skip(1); // '\\'
      // Committed to parse or throw exception.
      let sign = +1;
      let c = t.pop(); // 'p' or 'P'
      if (c === Codepoint.CODES.get('P')) {
        sign = -1;
      }
      if (!t.more()) {
        t.rewindTo(startPos);
        throw new RE2JSSyntaxException(Parser.ERR_INVALID_CHAR_RANGE, t.rest());
      }
      c = t.pop();
      let name;
      if (c !== Codepoint.CODES.get('{')) {
        // Single-letter name.
        name = Utils.runeToString(c);
      } else {
        // Name is in braces.
        const rest = t.rest();
        const end = rest.indexOf('}');
        if (end < 0) {
          t.rewindTo(startPos);
          throw new RE2JSSyntaxException(Parser.ERR_INVALID_CHAR_RANGE, t.rest());
        }
        name = rest.substring(0, end); // e.g. "Han"
        t.skipString(name);
        t.skip(1);
        // Don't use skip(end) because it assumes UTF-16 coding, and
        // StringIterator doesn't guarantee that.
      }
      // Group can have leading negation too.
      //  \p{^Han} == \P{Han}, \P{^Han} == \p{Han}.
      if (!(name.length === 0) && name.codePointAt(0) === Codepoint.CODES.get('^')) {
        sign = 0 - sign; // -sign
        name = name.substring(1);
      }
      const pair = Parser.unicodeTable(name);
      if (pair === null) {
        throw new RE2JSSyntaxException(Parser.ERR_INVALID_CHAR_RANGE, t.from(startPos));
      }
      const tab = pair.first;
      const fold = pair.second; // fold-equivalent table
      // Variation of CharClass.appendGroup() for tables.
      if ((this.flags & RE2Flags.FOLD_CASE) === 0 || fold === null) {
        cc.appendTableWithSign(tab, sign);
      } else {
        // Merge and clean tab and fold in a temporary buffer.
        // This is necessary for the negative case and just tidy
        // for the positive case.
        const tmp = new CharClass().appendTable(tab).appendTable(fold).cleanClass().toArray();
        cc.appendClassWithSign(tmp, sign);
      }
      return true;
    }

    // parseClass parses a character class and pushes it onto the parse stack.
    //
    // NOTES:
    // Pre: at '['; Post: after ']'.
    // Mutates stack.  Advances iterator.  May throw.
    parseClass(t) {
      const startPos = t.pos();
      t.skip(1); // '['
      const re = this.newRegexp(Regexp.Op.CHAR_CLASS);
      re.flags = this.flags;
      const cc = new CharClass();
      let sign = +1;
      if (t.more() && t.lookingAt('^')) {
        sign = -1;
        t.skip(1); // '^'
        // If character class does not match \n, add it here,
        // so that negation later will do the right thing.
        if ((this.flags & RE2Flags.CLASS_NL) === 0) {
          cc.appendRange(Codepoint.CODES.get('\n'), Codepoint.CODES.get('\n'));
        }
      }
      let first = true; // ']' and '-' are okay as first char in class
      while (!t.more() || t.peek() !== Codepoint.CODES.get(']') || first) {
        // POSIX: - is only okay unescaped as first or last in class.
        // Perl: - is okay anywhere.
        if (t.more() && t.lookingAt('-') && (this.flags & RE2Flags.PERL_X) === 0 && !first) {
          const s = t.rest();
          if (s === '-' || !s.startsWith('-]')) {
            t.rewindTo(startPos);
            throw new RE2JSSyntaxException(Parser.ERR_INVALID_CHAR_RANGE, t.rest());
          }
        }
        first = false;
        const beforePos = t.pos();
        // Look for POSIX [:alnum:] etc.
        if (t.lookingAt('[:')) {
          if (this.parseNamedClass(t, cc)) {
            continue;
          }
          t.rewindTo(beforePos);
        }

        // Look for Unicode character group like \p{Han}.
        if (this.parseUnicodeClass(t, cc)) {
          continue;
        }

        // Look for Perl character class symbols (extension).
        if (this.parsePerlClassEscape(t, cc)) {
          continue;
        }
        t.rewindTo(beforePos);

        // Single character or simple range.
        const lo = Parser.parseClassChar(t, startPos);
        let hi = lo;
        if (t.more() && t.lookingAt('-')) {
          t.skip(1);
          if (t.more() && t.lookingAt(']')) {
            // [a-] means (a|-) so check for final ].
            t.skip(-1);
          } else {
            hi = Parser.parseClassChar(t, startPos);
            if (hi < lo) {
              throw new RE2JSSyntaxException(Parser.ERR_INVALID_CHAR_RANGE, t.from(beforePos));
            }
          }
        }
        if ((this.flags & RE2Flags.FOLD_CASE) === 0) {
          cc.appendRange(lo, hi);
        } else {
          cc.appendFoldedRange(lo, hi);
        }
      }
      t.skip(1); // ']'

      cc.cleanClass();
      if (sign < 0) {
        cc.negateClass();
      }
      re.runes = cc.toArray();
      this.push(re);
    }
  }

  // A logical thread in the NFA.
  class Thread {
    constructor() {
      this.inst = null;
      this.cap = [];
    }
  }

  // A queue is a 'sparse array' holding pending threads of execution.  See:
  // research.swtch.com/2008/03/using-uninitialized-memory-for-fun-and.html
  class Queue {
    constructor() {
      this.sparse = []; // may contain stale but in-bounds values.
      this.densePcs = []; // may contain stale pc in slots >= size
      this.denseThreads = []; // may contain stale Thread in slots >= size
      this.size = 0;
    }
    contains(pc) {
      const j = this.sparse[pc];
      return j < this.size && this.densePcs[j] === pc;
    }
    isEmpty() {
      return this.size === 0;
    }
    add(pc) {
      const j = this.size++;
      this.sparse[pc] = j;
      this.denseThreads[j] = null;
      this.densePcs[j] = pc;
      return j;
    }
    clear() {
      this.sparse = [];
      this.densePcs = [];
      this.denseThreads = [];
      this.size = 0;
    }
    toString() {
      let out = '{';
      for (let i = 0; i < this.size; i++) {
        if (i !== 0) {
          out += ', ';
        }
        out += this.densePcs[i];
      }
      out += '}';
      return out;
    }
  }
  // A Machine matches an input string of Unicode characters against an
  // RE2 instance using a simple NFA.
  //
  // Called by RE2.doExecute.
  class Machine {
    static fromRE2(re2) {
      const m = new Machine();
      m.prog = re2.prog;
      m.re2 = re2;
      m.q0 = new Queue(m.prog.numInst());
      m.q1 = new Queue(m.prog.numInst());
      m.pool = [];
      m.poolSize = 0;
      m.matched = false;
      m.matchcap = Array(m.prog.numCap < 2 ? 2 : m.prog.numCap).fill(0);
      m.ncap = 0;
      return m;
    }
    static fromMachine(machine) {
      const m = new Machine();
      m.re2 = machine.re2;
      m.prog = machine.prog;
      m.q0 = machine.q0;
      m.q1 = machine.q1;
      m.pool = machine.pool;
      m.poolSize = machine.poolSize;
      m.matched = machine.matched;
      m.matchcap = machine.matchcap;
      m.ncap = machine.ncap;
      return m;
    }

    // init() reinitializes an existing Machine for re-use on a new input.
    init(ncap) {
      this.ncap = ncap;
      if (ncap > this.matchcap.length) {
        this.initNewCap(ncap);
      } else {
        this.resetCap(ncap);
      }
    }
    resetCap(ncap) {
      for (let i = 0; i < this.poolSize; i++) {
        const t = this.pool[i];
        t.cap = Array(ncap).fill(0);
      }
    }
    initNewCap(ncap) {
      for (let i = 0; i < this.poolSize; i++) {
        const t = this.pool[i];
        t.cap = Array(ncap).fill(0);
      }
      this.matchcap = Array(ncap).fill(0);
    }
    submatches() {
      if (this.ncap === 0) {
        return Utils.emptyInts();
      }
      return this.matchcap.slice(0, this.ncap);
    }

    // alloc() allocates a new thread with the given instruction.
    // It uses the free pool if possible.
    alloc(inst) {
      let t;
      if (this.poolSize > 0) {
        this.poolSize--;
        t = this.pool[this.poolSize];
      } else {
        t = new Thread();
      }
      t.inst = inst;
      return t;
    }

    // Frees all threads on the thread queue, returning them to the free pool.
    freeQueue(queue, from = 0) {
      const numberOfThread = queue.size - from;
      const requiredPoolLength = this.poolSize + numberOfThread;
      if (this.pool.length < requiredPoolLength) {
        this.pool = this.pool.slice(0, Math.max(this.pool.length * 2, requiredPoolLength));
      }
      for (let i = from; i < queue.size; i++) {
        const t = queue.denseThreads[i];
        if (t !== null) {
          this.pool[this.poolSize] = t;
          this.poolSize++;
        }
      }
      queue.clear();
    }

    // freeThread() returns t to the free pool.
    freeThread(t) {
      if (this.pool.length <= this.poolSize) {
        this.pool = this.pool.slice(0, this.pool.length * 2);
      }
      this.pool[this.poolSize] = t;
      this.poolSize++;
    }
    match(input, pos, anchor) {
      const startCond = this.re2.cond;
      if (startCond === Utils.EMPTY_ALL) {
        return false;
      }
      if ((anchor === RE2Flags.ANCHOR_START || anchor === RE2Flags.ANCHOR_BOTH) && pos !== 0) {
        return false;
      }
      this.matched = false;
      this.matchcap = Array(this.prog.numCap).fill(-1);
      let runq = this.q0;
      let nextq = this.q1;
      let r = input.step(pos);
      let rune = r >> 3;
      let width = r & 7;
      let rune1 = -1;
      let width1 = 0;
      if (r !== MachineInputBase.EOF()) {
        r = input.step(pos + width);
        rune1 = r >> 3;
        width1 = r & 7;
      }
      let flag;
      if (pos === 0) {
        flag = Utils.emptyOpContext(-1, rune);
      } else {
        flag = input.context(pos);
      }
      // eslint-disable-next-line no-constant-condition
      while (true) {
        if (runq.isEmpty()) {
          if ((startCond & Utils.EMPTY_BEGIN_TEXT) !== 0 && pos !== 0) {
            break;
          }
          if (this.matched) {
            break;
          }
          if (!(this.re2.prefix.length === 0) && rune1 !== this.re2.prefixRune && input.canCheckPrefix()) {
            const advance = input.index(this.re2, pos);
            if (advance < 0) {
              break;
            }
            pos += advance;
            r = input.step(pos);
            rune = r >> 3;
            width = r & 7;
            r = input.step(pos + width);
            rune1 = r >> 3;
            width1 = r & 7;
          }
        }
        if (!this.matched && (pos === 0 || anchor === RE2Flags.UNANCHORED)) {
          if (this.ncap > 0) {
            this.matchcap[0] = pos;
          }
          this.add(runq, this.prog.start, pos, this.matchcap, flag, null);
        }
        const nextPos = pos + width;
        flag = input.context(nextPos);
        this.step(runq, nextq, pos, nextPos, rune, flag, anchor, pos === input.endPos());
        if (width === 0) {
          break;
        }
        if (this.ncap === 0 && this.matched) {
          break;
        }
        pos += width;
        rune = rune1;
        width = width1;
        if (rune !== -1) {
          r = input.step(pos + width);
          rune1 = r >> 3;
          width1 = r & 7;
        }
        const tmpq = runq;
        runq = nextq;
        nextq = tmpq;
      }
      this.freeQueue(nextq);
      return this.matched;
    }
    step(runq, nextq, pos, nextPos, c, nextCond, anchor, atEnd) {
      const longest = this.re2.longest;
      for (let j = 0; j < runq.size; j++) {
        let t = runq.denseThreads[j];
        if (t === null) {
          continue;
        }
        if (longest && this.matched && this.ncap > 0 && this.matchcap[0] < t.cap[0]) {
          this.freeThread(t);
          continue;
        }
        const i = t.inst;
        let add = false;
        switch (i.op) {
          case Inst.MATCH:
            if (anchor === RE2Flags.ANCHOR_BOTH && !atEnd) {
              break;
            }
            if (this.ncap > 0 && (!longest || !this.matched || this.matchcap[1] < pos)) {
              t.cap[1] = pos;
              this.matchcap = t.cap.slice(0, this.ncap);
            }
            if (!longest) {
              this.freeQueue(runq, j + 1);
            }
            this.matched = true;
            break;
          case Inst.RUNE:
            add = i.matchRune(c);
            break;
          case Inst.RUNE1:
            add = c === i.runes[0];
            break;
          case Inst.RUNE_ANY:
            add = true;
            break;
          case Inst.RUNE_ANY_NOT_NL:
            add = c !== Codepoint.CODES.get('\n');
            break;
          default:
            throw new Error('bad inst');
        }
        if (add) {
          t = this.add(nextq, i.out, nextPos, t.cap, nextCond, t);
        }
        if (t !== null) {
          this.freeThread(t);
          runq.denseThreads[j] = null;
        }
      }
      runq.clear();
    }
    add(q, pc, pos, cap, cond, t) {
      if (pc === 0) {
        return t;
      }
      if (q.contains(pc)) {
        return t;
      }
      const d = q.add(pc);
      const inst = this.prog.inst[pc];
      switch (inst.op) {
        case Inst.FAIL:
          break;
        case Inst.ALT:
        case Inst.ALT_MATCH:
          t = this.add(q, inst.out, pos, cap, cond, t);
          t = this.add(q, inst.arg, pos, cap, cond, t);
          break;
        case Inst.EMPTY_WIDTH:
          if ((inst.arg & ~cond) === 0) {
            t = this.add(q, inst.out, pos, cap, cond, t);
          }
          break;
        case Inst.NOP:
          t = this.add(q, inst.out, pos, cap, cond, t);
          break;
        case Inst.CAPTURE:
          if (inst.arg < this.ncap) {
            const opos = cap[inst.arg];
            cap[inst.arg] = pos;
            this.add(q, inst.out, pos, cap, cond, null);
            cap[inst.arg] = opos;
          } else {
            t = this.add(q, inst.out, pos, cap, cond, t);
          }
          break;
        case Inst.MATCH:
        case Inst.RUNE:
        case Inst.RUNE1:
        case Inst.RUNE_ANY:
        case Inst.RUNE_ANY_NOT_NL:
          if (t === null) {
            t = this.alloc(inst);
          } else {
            t.inst = inst;
          }
          if (this.ncap > 0 && t.cap !== cap) {
            t.cap = cap.slice(0, this.ncap);
          }
          q.denseThreads[d] = t;
          t = null;
          break;
        default:
          throw new Error('unhandled');
      }
      return t;
    }
  }

  class AtomicReference {
    constructor(initialValue) {
      this.value = initialValue;
    }

    // Returns the current value
    get() {
      return this.value;
    }

    // Sets to the given value
    set(newValue) {
      this.value = newValue;
    }

    // Atomically sets to the given value and returns true if the current value == the expected value
    compareAndSet(expect, update) {
      if (this.value === expect) {
        this.value = update;
        return true;
      }
      return false;
    }
  }

  /**
   * An RE2 class instance is a compiled representation of an RE2 regular expression, independent of
   * the public Java-like Pattern/Matcher API.
   *
   * This class also contains various implementation helpers for RE2 regular expressions.
   *
   * Use the {@link #quoteMeta(String)} utility function to quote all regular expression
   * metacharacters in an arbitrary string.
   *
   */
  class RE2 {
    // This is visible for testing.
    static initTest(expr) {
      const re2 = RE2.compile(expr);
      const res = new RE2(re2.expr, re2.prog, re2.numSubexp, re2.longest);
      res.cond = re2.cond;
      res.prefix = re2.prefix;
      res.prefixUTF8 = re2.prefixUTF8;
      res.prefixComplete = re2.prefixComplete;
      res.prefixRune = re2.prefixRune;
      return res;
    }

    /**
     * Parses a regular expression and returns, if successful, an {@code RE2} instance that can be
     * used to match against text.
     *
     * When matching against text, the regexp returns a match that begins as early as possible in the
     * input (leftmost), and among those it chooses the one that a backtracking search would have
     * found first. This so-called leftmost-first matching is the same semantics that Perl, Python,
     * and other implementations use, although this package implements it without the expense of
     * backtracking. For POSIX leftmost-longest matching, see {@link #compilePOSIX}.
     */
    static compile(expr) {
      return RE2.compileImpl(expr, RE2Flags.PERL, false);
    }

    /**
     * {@code compilePOSIX} is like {@link #compile} but restricts the regular expression to POSIX ERE
     * (egrep) syntax and changes the match semantics to leftmost-longest.
     *
     * That is, when matching against text, the regexp returns a match that begins as early as
     * possible in the input (leftmost), and among those it chooses a match that is as long as
     * possible. This so-called leftmost-longest matching is the same semantics that early regular
     * expression implementations used and that POSIX specifies.
     *
     * However, there can be multiple leftmost-longest matches, with different submatch choices, and
     * here this package diverges from POSIX. Among the possible leftmost-longest matches, this
     * package chooses the one that a backtracking search would have found first, while POSIX
     * specifies that the match be chosen to maximize the length of the first subexpression, then the
     * second, and so on from left to right. The POSIX rule is computationally prohibitive and not
     * even well-defined. See http://swtch.com/~rsc/regexp/regexp2.html#posix
     */
    static compilePOSIX(expr) {
      return RE2.compileImpl(expr, RE2Flags.POSIX, true);
    }

    // Exposed to ExecTests.
    static compileImpl(expr, mode, longest) {
      let re = Parser.parse(expr, mode);
      const maxCap = re.maxCap();
      re = Simplify.simplify(re);
      const prog = Compiler.compileRegexp(re);
      const re2 = new RE2(expr, prog, maxCap, longest);
      const [prefixCompl, prefixStr] = prog.prefix();
      re2.prefixComplete = prefixCompl;
      re2.prefix = prefixStr;
      re2.prefixUTF8 = Utils.stringToUtf8ByteArray(re2.prefix);
      if (re2.prefix.length > 0) {
        re2.prefixRune = re2.prefix.codePointAt(0);
      }
      re2.namedGroups = re.namedGroups;
      return re2;
    }

    /**
     * Returns true iff textual regular expression {@code pattern} matches string {@code s}.
     *
     * More complicated queries need to use {@link #compile} and the full {@code RE2} interface.
     */
    // This is visible for testing.
    static match(pattern, s) {
      return RE2.compile(pattern).match(s);
    }
    constructor(expr, prog, numSubexp = 0, longest = 0) {
      this.expr = expr; // as passed to Compile
      this.prog = prog; // compiled program
      this.numSubexp = numSubexp;
      this.longest = longest;
      this.cond = prog.startCond(); // EMPTY_* bitmask: empty-width conditions
      this.prefix = null; // required UTF-16 prefix in unanchored matches
      this.prefixUTF8 = null; // required UTF-8 prefix in unanchored matches
      this.prefixComplete = false; // true if prefix is the entire regexp
      this.prefixRune = 0; // first rune in prefix
      this.pooled = new AtomicReference(); // Cache of machines for running regexp. Forms a Treiber stack.
    }

    /**
     * Returns the number of parenthesized subexpressions in this regular expression.
     */
    numberOfCapturingGroups() {
      return this.numSubexp;
    }

    // get() returns a machine to use for matching |this|.  It uses |this|'s
    // machine cache if possible, to avoid unnecessary allocation.
    get() {
      // Pop a machine off the stack if available.
      let head;
      do {
        head = this.pooled.get();
      } while (head && !this.pooled.compareAndSet(head, head.next));
      return head;
    }

    // Clears the memory associated with this machine.
    reset() {
      this.pooled.set(null);
    }

    // put() returns a machine to |this|'s machine cache.  There is no attempt to
    // limit the size of the cache, so it will grow to the maximum number of
    // simultaneous matches run using |this|.  (The cache empties when |this|
    // gets garbage collected or reset is called.)
    put(m, isNew) {
      // To avoid allocation in the single-thread or uncontended case, reuse a node only if
      // it was the only element in the stack when it was popped, and it's the only element
      // in the stack when it's pushed back after use.
      let head = this.pooled.get();
      do {
        head = this.pooled.get();
        if (!isNew && head) {
          // If an element had a null next pointer and it was previously in the stack, another thread
          // might be trying to pop it out right now, and if it sees the same node now in the
          // stack the pop will succeed, but the new top of the stack will be the stale (null) value
          // of next. Allocate a new Machine so that the CAS will not succeed if this node has been
          // popped and re-pushed.
          m = Machine.fromMachine(m);
          isNew = true;
        }

        // Without this comparison, TSAN will complain about a race condition:
        // Thread A, B, and C all attempt to do a match on the same pattern.
        //
        // A: Allocates Machine 1; executes match; put machine 1. State is now:
        //
        // pooled -> machine 1 -> null
        //
        // B reads pooled, sees machine 1
        //
        // C reads pooled, sees machine 1
        //
        // B successfully CASes pooled to null
        //
        // B executes match; put machine 1, which involves setting machine1.next to
        // null (even though it's already null); preempted before CAS
        //
        // C resumes, and reads machine1.next in order to execute cas(head, head.next)
        //
        // There is no happens-before relationship between B's redundant null write
        // and C's read, thus triggering TSAN.
        //
        // Not needed for JS code
        if (m.next !== head) {
          m.next = head;
        }
      } while (!this.pooled.compareAndSet(head, m));
    }
    toString() {
      return this.expr;
    }

    // doExecute() finds the leftmost match in the input and returns
    // the position of its subexpressions.
    // Derived from exec.go.
    doExecute(input, pos, anchor, ncap) {
      let m = this.get();
      // The Treiber stack cannot reuse nodes, unless the node to be reused has only ever been at
      // the bottom of the stack (i.e., next == null).
      let isNew = false;
      if (!m) {
        m = Machine.fromRE2(this);
        isNew = true;
      } else if (m.next !== null) {
        m = Machine.fromMachine(m);
        isNew = true;
      }
      m.init(ncap);
      const cap = m.match(input, pos, anchor) ? m.submatches() : null;
      this.put(m, isNew);
      return cap;
    }
    match(s) {
      return this.doExecute(MachineInput.fromUTF16(s), 0, RE2Flags.UNANCHORED, 0) !== null;
    }

    /**
     * Matches the regular expression against input starting at position start and ending at position
     * end, with the given anchoring. Records the submatch boundaries in group, which is [start, end)
     * pairs of byte offsets. The number of boundaries needed is inferred from the size of the group
     * array. It is most efficient not to ask for submatch boundaries.
     *
     * @param input the input byte array
     * @param start the beginning position in the input
     * @param end the end position in the input
     * @param anchor the anchoring flag (UNANCHORED, ANCHOR_START, ANCHOR_BOTH)
     * @param group the array to fill with submatch positions
     * @param ngroup the number of array pairs to fill in
     * @returns true if a match was found
     */
    matchWithGroup(input, start, end, anchor, ngroup) {
      if (!(input instanceof MatcherInputBase)) {
        input = MatcherInput.utf16(input);
      }
      return this.matchMachineInput(input, start, end, anchor, ngroup);
    }
    matchMachineInput(input, start, end, anchor, ngroup) {
      if (start > end) {
        return [false, null];
      }
      const machineInput = input.isUTF16Encoding() ? MachineInput.fromUTF16(input.asCharSequence(), 0, end) : MachineInput.fromUTF8(input.asBytes(), 0, end);
      const groupMatch = this.doExecute(machineInput, start, anchor, 2 * ngroup);
      if (groupMatch === null) {
        return [false, null];
      }
      return [true, groupMatch];
    }

    /**
     * Returns true iff this regexp matches the UTF-8 byte array {@code b}.
     */
    // This is visible for testing.
    matchUTF8(b) {
      return this.doExecute(MachineInput.fromUTF8(b), 0, RE2Flags.UNANCHORED, 0) !== null;
    }

    /**
     * Returns a copy of {@code src} in which all matches for this regexp have been replaced by
     * {@code repl}. No support is provided for expressions (e.g. {@code \1} or {@code $1}) in the
     * replacement string.
     */
    // This is visible for testing.
    replaceAll(src, repl) {
      return this.replaceAllFunc(src, () => repl, 2 * src.length + 1);
    }

    /**
     * Returns a copy of {@code src} in which only the first match for this regexp has been replaced
     * by {@code repl}. No support is provided for expressions (e.g. {@code \1} or {@code $1}) in the
     * replacement string.
     */
    // This is visible for testing.
    replaceFirst(src, repl) {
      return this.replaceAllFunc(src, () => repl, 1);
    }

    /**
     * Returns a copy of {@code src} in which at most {@code maxReplaces} matches for this regexp have
     * been replaced by the return value of of function {@code repl} (whose first argument is the
     * matched string). No support is provided for expressions (e.g. {@code \1} or {@code $1}) in the
     * replacement string.
     */
    // This is visible for testing.
    replaceAllFunc(src, replFunc, maxReplaces) {
      let lastMatchEnd = 0;
      let searchPos = 0;
      let out = '';
      const input = MachineInput.fromUTF16(src);
      let numReplaces = 0;
      while (searchPos <= src.length) {
        const a = this.doExecute(input, searchPos, RE2Flags.UNANCHORED, 2);
        if (a === null || a.length === 0) {
          break;
        }
        out += src.substring(lastMatchEnd, a[0]);
        if (a[1] > lastMatchEnd || a[0] === 0) {
          out += replFunc(src.substring(a[0], a[1]));
          numReplaces++;
        }
        lastMatchEnd = a[1];
        const width = input.step(searchPos) & 7;
        if (searchPos + width > a[1]) {
          searchPos += width;
        } else if (searchPos + 1 > a[1]) {
          searchPos++;
        } else {
          searchPos = a[1];
        }
        if (numReplaces >= maxReplaces) {
          break;
        }
      }
      out += src.substring(lastMatchEnd);
      return out;
    }

    // The number of capture values in the program may correspond
    // to fewer capturing expressions than are in the regexp.
    // For example, "(a){0}" turns into an empty program, so the
    // maximum capture in the program is 0 but we need to return
    // an expression for \1.  Pad returns a with -1s appended as needed;
    // the result may alias a.
    pad(a) {
      if (a === null) {
        return null;
      }
      let n = (1 + this.numSubexp) * 2;
      if (a.length < n) {
        let a2 = new Array(n).fill(-1);
        for (let i = 0; i < a.length; i++) {
          a2[i] = a[i];
        }
        a = a2;
      }
      return a;
    }

    // Find matches in input.
    allMatches(input, n, deliverFun = v => v) {
      let result = [];
      const end = input.endPos();
      if (n < 0) {
        n = end + 1;
      }
      let pos = 0;
      let i = 0;
      let prevMatchEnd = -1;
      while (i < n && pos <= end) {
        const matches = this.doExecute(input, pos, RE2Flags.UNANCHORED, this.prog.numCap);
        if (matches === null || matches.length === 0) {
          break;
        }
        let accept = true;
        if (matches[1] === pos) {
          if (matches[0] === prevMatchEnd) {
            accept = false;
          }
          const r = input.step(pos);
          if (r < 0) {
            pos = end + 1;
          } else {
            pos += r & 7;
          }
        } else {
          pos = matches[1];
        }
        prevMatchEnd = matches[1];
        if (accept) {
          result.push(deliverFun(this.pad(matches)));
          i++;
        }
      }
      return result;
    }

    // Legacy Go-style interface; preserved (package-private) for better
    // test coverage.
    //
    // There are 16 methods of RE2 that match a regular expression and
    // identify the matched text.  Their names are matched by this regular
    // expression:
    //
    //    find(All)?(UTF8)?(Submatch)?(Index)?
    //
    // If 'All' is present, the routine matches successive non-overlapping
    // matches of the entire expression.  Empty matches abutting a
    // preceding match are ignored.  The return value is an array
    // containing the successive return values of the corresponding
    // non-All routine.  These routines take an extra integer argument, n;
    // if n >= 0, the function returns at most n matches/submatches.
    //
    // If 'UTF8' is present, the argument is a UTF-8 encoded byte[] array;
    // otherwise it is a UTF-16 encoded js string; return values
    // are adjusted as appropriate.
    //
    // If 'Submatch' is present, the return value is an list identifying
    // the successive submatches of the expression.  Submatches are
    // matches of parenthesized subexpressions within the regular
    // expression, numbered from left to right in order of opening
    // parenthesis.  Submatch 0 is the match of the entire expression,
    // submatch 1 the match of the first parenthesized subexpression, and
    // so on.
    //
    // If 'Index' is present, matches and submatches are identified by
    // byte index pairs within the input string: result[2*n:2*n+1]
    // identifies the indexes of the nth submatch.  The pair for n==0
    // identifies the match of the entire expression.  If 'Index' is not
    // present, the match is identified by the text of the match/submatch.
    // If an index is negative, it means that subexpression did not match
    // any string in the input.

    /**
     * Returns an array holding the text of the leftmost match in {@code b} of this regular
     * expression.
     *
     * A return value of null indicates no match.
     */
    // This is visible for testing.
    findUTF8(b) {
      const a = this.doExecute(MachineInput.fromUTF8(b), 0, RE2Flags.UNANCHORED, 2);
      if (a === null) {
        return null;
      }
      return b.slice(a[0], a[1]);
    }

    /**
     * Returns a two-element array of integers defining the location of the leftmost match in
     * {@code b} of this regular expression. The match itself is at {@code b[loc[0]...loc[1]]}.
     *
     * A return value of null indicates no match.
     */
    // This is visible for testing.
    findUTF8Index(b) {
      const a = this.doExecute(MachineInput.fromUTF8(b), 0, RE2Flags.UNANCHORED, 2);
      if (a === null) {
        return null;
      }
      return a.slice(0, 2);
    }

    /**
     * Returns a string holding the text of the leftmost match in {@code s} of this regular
     * expression.
     *
     * If there is no match, the return value is an empty string, but it will also be empty if the
     * regular expression successfully matches an empty string. Use {@link #findIndex} or
     * {@link #findSubmatch} if it is necessary to distinguish these cases.
     */
    // This is visible for testing.
    find(s) {
      const a = this.doExecute(MachineInput.fromUTF16(s), 0, RE2Flags.UNANCHORED, 2);
      if (a === null) {
        return '';
      }
      return s.substring(a[0], a[1]);
    }

    /**
     * Returns a two-element array of integers defining the location of the leftmost match in
     * {@code s} of this regular expression. The match itself is at
     * {@code s.substring(loc[0], loc[1])}.
     *
     * A return value of null indicates no match.
     */
    // This is visible for testing.
    findIndex(s) {
      return this.doExecute(MachineInput.fromUTF16(s), 0, RE2Flags.UNANCHORED, 2);
    }

    /**
     * Returns an array of arrays the text of the leftmost match of the regular expression in
     * {@code b} and the matches, if any, of its subexpressions, as defined by the <a
     * href='#submatch'>Submatch</a> description above.
     *
     * A return value of null indicates no match.
     */
    // This is visible for testing.
    findUTF8Submatch(b) {
      const a = this.doExecute(MachineInput.fromUTF8(b), 0, RE2Flags.UNANCHORED, this.prog.numCap);
      if (a === null) {
        return null;
      }
      const ret = new Array(1 + this.numSubexp).fill(null);
      for (let i = 0; i < ret.length; i++) {
        if (2 * i < a.length && a[2 * i] >= 0) {
          ret[i] = b.slice(a[2 * i], a[2 * i + 1]);
        }
      }
      return ret;
    }

    /**
     * Returns an array holding the index pairs identifying the leftmost match of this regular
     * expression in {@code b} and the matches, if any, of its subexpressions, as defined by the the
     * <a href='#submatch'>Submatch</a> and <a href='#index'>Index</a> descriptions above.
     *
     * A return value of null indicates no match.
     */
    // This is visible for testing.
    findUTF8SubmatchIndex(b) {
      return this.pad(this.doExecute(MachineInput.fromUTF8(b), 0, RE2Flags.UNANCHORED, this.prog.numCap));
    }

    /**
     * Returns an array of strings holding the text of the leftmost match of the regular expression in
     * {@code s} and the matches, if any, of its subexpressions, as defined by the <a
     * href='#submatch'>Submatch</a> description above.
     *
     * A return value of null indicates no match.
     */
    // This is visible for testing.
    findSubmatch(s) {
      const a = this.doExecute(MachineInput.fromUTF16(s), 0, RE2Flags.UNANCHORED, this.prog.numCap);
      if (a === null) {
        return null;
      }
      const ret = new Array(1 + this.numSubexp).fill(null);
      for (let i = 0; i < ret.length; i++) {
        if (2 * i < a.length && a[2 * i] >= 0) {
          ret[i] = s.substring(a[2 * i], a[2 * i + 1]);
        }
      }
      return ret;
    }

    /**
     * Returns an array holding the index pairs identifying the leftmost match of this regular
     * expression in {@code s} and the matches, if any, of its subexpressions, as defined by the <a
     * href='#submatch'>Submatch</a> description above.
     *
     * A return value of null indicates no match.
     */
    // This is visible for testing.
    findSubmatchIndex(s) {
      return this.pad(this.doExecute(MachineInput.fromUTF16(s), 0, RE2Flags.UNANCHORED, this.prog.numCap));
    }

    /**
     * {@code findAllUTF8()} is the <a href='#all'>All</a> version of {@link #findUTF8}; it returns a
     * list of up to {@code n} successive matches of the expression, as defined by the <a
     * href='#all'>All</a> description above.
     *
     * A return value of null indicates no match.
     *
     * TODO(adonovan): think about defining a byte slice view class, like a read-only Go slice backed
     * by |b|.
     */
    // This is visible for testing.
    findAllUTF8(b, n) {
      const result = this.allMatches(MachineInput.fromUTF8(b), n, match => b.slice(match[0], match[1]));
      if (result.length === 0) {
        return null;
      }
      return result;
    }

    /**
     * {@code findAllUTF8Index} is the <a href='#all'>All</a> version of {@link #findUTF8Index}; it
     * returns a list of up to {@code n} successive matches of the expression, as defined by the <a
     * href='#all'>All</a> description above.
     *
     * A return value of null indicates no match.
     */
    // This is visible for testing.
    findAllUTF8Index(b, n) {
      const result = this.allMatches(MachineInput.fromUTF8(b), n, match => match.slice(0, 2));
      if (result.length === 0) {
        return null;
      }
      return result;
    }

    /**
     * {@code findAll} is the <a href='#all'>All</a> version of {@link #find}; it returns a list of up
     * to {@code n} successive matches of the expression, as defined by the <a href='#all'>All</a>
     * description above.
     *
     * A return value of null indicates no match.
     */
    // This is visible for testing.
    findAll(s, n) {
      const result = this.allMatches(MachineInput.fromUTF16(s), n, match => s.substring(match[0], match[1]));
      if (result.length === 0) {
        return null;
      }
      return result;
    }

    /**
     * {@code findAllIndex} is the <a href='#all'>All</a> version of {@link #findIndex}; it returns a
     * list of up to {@code n} successive matches of the expression, as defined by the <a
     * href='#all'>All</a> description above.
     *
     * A return value of null indicates no match.
     */
    // This is visible for testing.
    findAllIndex(s, n) {
      const result = this.allMatches(MachineInput.fromUTF16(s), n, match => match.slice(0, 2));
      if (result.length === 0) {
        return null;
      }
      return result;
    }

    /**
     * {@code findAllUTF8Submatch} is the <a href='#all'>All</a> version of {@link #findUTF8Submatch};
     * it returns a list of up to {@code n} successive matches of the expression, as defined by the <a
     * href='#all'>All</a> description above.
     *
     * A return value of null indicates no match.
     */
    // This is visible for testing.
    findAllUTF8Submatch(b, n) {
      const result = this.allMatches(MachineInput.fromUTF8(b), n, match => {
        let slice = new Array(match.length / 2 | 0).fill(null);
        for (let j = 0; j < slice.length; j++) {
          if (match[2 * j] >= 0) {
            slice[j] = b.slice(match[2 * j], match[2 * j + 1]);
          }
        }
        return slice;
      });
      if (result.length === 0) {
        return null;
      }
      return result;
    }

    /**
     * {@code findAllUTF8SubmatchIndex} is the <a href='#all'>All</a> version of
     * {@link #findUTF8SubmatchIndex}; it returns a list of up to {@code n} successive matches of the
     * expression, as defined by the <a href='#all'>All</a> description above.
     *
     * A return value of null indicates no match.
     */
    // This is visible for testing.
    findAllUTF8SubmatchIndex(b, n) {
      const result = this.allMatches(MachineInput.fromUTF8(b), n);
      if (result.length === 0) {
        return null;
      }
      return result;
    }

    /**
     * {@code findAllSubmatch} is the <a href='#all'>All</a> version of {@link #findSubmatch}; it
     * returns a list of up to {@code n} successive matches of the expression, as defined by the <a
     * href='#all'>All</a> description above.
     *
     * A return value of null indicates no match.
     */
    // This is visible for testing.
    findAllSubmatch(s, n) {
      const result = this.allMatches(MachineInput.fromUTF16(s), n, match => {
        let slice = new Array(match.length / 2 | 0).fill(null);
        for (let j = 0; j < slice.length; j++) {
          if (match[2 * j] >= 0) {
            slice[j] = s.substring(match[2 * j], match[2 * j + 1]);
          }
        }
        return slice;
      });
      if (result.length === 0) {
        return null;
      }
      return result;
    }

    /**
     * {@code findAllSubmatchIndex} is the <a href='#all'>All</a> version of
     * {@link #findSubmatchIndex}; it returns a list of up to {@code n} successive matches of the
     * expression, as defined by the <a href='#all'>All</a> description above.
     *
     * A return value of null indicates no match.
     */
    // This is visible for testing.
    findAllSubmatchIndex(s, n) {
      const result = this.allMatches(MachineInput.fromUTF16(s), n);
      if (result.length === 0) {
        return null;
      }
      return result;
    }
  }

  /**
   * A compiled representation of an RE2 regular expression
   *
   * The matching functions take {@code String} arguments instead of the more general Java
   * {@code CharSequence} since the latter doesn't provide UTF-16 decoding.
   *
   *
   * @author rsc@google.com (Russ Cox)
   * @class
   */
  class RE2JS {
    /**
     * Flag: case insensitive matching.
     */
    static CASE_INSENSITIVE = 1;
    /**
     * Flag: dot ({@code .}) matches all characters, including newline.
     */
    static DOTALL = 2;
    /**
     * Flag: multiline matching: {@code ^} and {@code $} match at beginning and end of line, not just
     * beginning and end of input.
     */
    static MULTILINE = 4;
    /**
     * Flag: Unicode groups (e.g. {@code \p\ Greek\} ) will be syntax errors.
     */
    static DISABLE_UNICODE_GROUPS = 8;
    /**
     * Flag: matches longest possible string.
     */
    static LONGEST_MATCH = 16;

    /**
     * Returns a literal pattern string for the specified string.
     *
     * This method produces a string that can be used to create a <code>RE2JS</code> that would
     * match the string <code>s</code> as if it were a literal pattern.
     *
     * Metacharacters or escape sequences in the input sequence will be given no special meaning.
     *
     * @param {string} str The string to be literalized
     * @returns {string} A literal string replacement
     */
    static quote(str) {
      return Utils.quoteMeta(str);
    }

    /**
     * Helper: create new RE2JS with given regex and flags. Flregex is the regex with flags applied.
     * @param {string} regex
     * @param {number} [flags=0]
     * @returns {RE2JS}
     */
    static compile(regex, flags = 0) {
      let fregex = regex;
      if ((flags & RE2JS.CASE_INSENSITIVE) !== 0) {
        fregex = `(?i)${fregex}`;
      }
      if ((flags & RE2JS.DOTALL) !== 0) {
        fregex = `(?s)${fregex}`;
      }
      if ((flags & RE2JS.MULTILINE) !== 0) {
        fregex = `(?m)${fregex}`;
      }
      if ((flags & ~(RE2JS.MULTILINE | RE2JS.DOTALL | RE2JS.CASE_INSENSITIVE | RE2JS.DISABLE_UNICODE_GROUPS | RE2JS.LONGEST_MATCH)) !== 0) {
        throw new RE2JSFlagsException('Flags should only be a combination of MULTILINE, DOTALL, CASE_INSENSITIVE, DISABLE_UNICODE_GROUPS, LONGEST_MATCH');
      }
      let re2Flags = RE2Flags.PERL;
      if ((flags & RE2JS.DISABLE_UNICODE_GROUPS) !== 0) {
        re2Flags &= ~RE2Flags.UNICODE_GROUPS;
      }
      const p = new RE2JS(regex, flags);
      // The compiled RE2 regexp.
      p.re2Input = RE2.compileImpl(fregex, re2Flags, (flags & RE2JS.LONGEST_MATCH) !== 0);
      return p;
    }

    /**
     * Matches a string against a regular expression.
     *
     * @param {string} regex the regular expression
     * @param {string|number[]} input the input
     * @returns {boolean} true if the regular expression matches the entire input
     * @throws RE2JSSyntaxException if the regular expression is malformed
     */
    static matches(regex, input) {
      return RE2JS.compile(regex).matcher(input).matches();
    }

    /**
     * This is visible for testing.
     * @private
     */
    static initTest(pattern, flags, re2) {
      if (pattern == null) {
        throw new Error('pattern is null');
      }
      if (re2 == null) {
        throw new Error('re2 is null');
      }
      const p = new RE2JS(pattern, flags);
      // The compiled RE2 regexp.
      p.re2Input = re2;
      return p;
    }

    /**
     *
     * @param {string} pattern
     * @param {number} flags
     */
    constructor(pattern, flags) {
      // The pattern string at construction time.
      this.patternInput = pattern;
      // The flags at construction time.
      this.flagsInput = flags;
    }

    /**
     * Releases memory used by internal caches associated with this pattern. Does not change the
     * observable behaviour. Useful for tests that detect memory leaks via allocation tracking.
     */
    reset() {
      this.re2Input.reset();
    }

    /**
     * Returns the flags used in the constructor.
     * @returns {number}
     */
    flags() {
      return this.flagsInput;
    }

    /**
     * Returns the pattern used in the constructor.
     * @returns {string}
     */
    pattern() {
      return this.patternInput;
    }
    re2() {
      return this.re2Input;
    }

    /**
     * Matches a string against a regular expression.
     *
     * @param {string|number[]} input the input
     * @returns {boolean} true if the regular expression matches the entire input
     */
    matches(input) {
      return this.matcher(input).matches();
    }

    /**
     * Creates a new {@code Matcher} matching the pattern against the input.
     *
     * @param {string|number[]} input the input string
     * @returns {Matcher}
     */
    matcher(input) {
      if (Array.isArray(input)) {
        input = MatcherInput.utf8(input);
      }
      return new Matcher(this, input);
    }

    /**
     * Splits input around instances of the regular expression. It returns an array giving the strings
     * that occur before, between, and after instances of the regular expression.
     *
     * If {@code limit <= 0}, there is no limit on the size of the returned array. If
     * {@code limit == 0}, empty strings that would occur at the end of the array are omitted. If
     * {@code limit > 0}, at most limit strings are returned. The final string contains the remainder
     * of the input, possibly including additional matches of the pattern.
     *
     * @param {string} input the input string to be split
     * @param {number} [limit=0] the limit
     * @returns {string[]} the split strings
     */
    split(input, limit = 0) {
      const m = this.matcher(input);
      const result = [];
      let emptiesSkipped = 0;
      let last = 0;
      while (m.find()) {
        if (last === 0 && m.end() === 0) {
          // Zero-width match at the beginning, skip
          last = m.end();
          continue;
        }
        if (limit > 0 && result.length === limit - 1) {
          // no more room for matches
          break;
        }
        if (last === m.start()) {
          // Empty match, may or may not be trailing.
          if (limit === 0) {
            emptiesSkipped += 1;
            last = m.end();
            continue;
          }
        } else {
          // If emptiesSkipped > 0 then limit == 0 and we have non-trailing empty matches to add before
          // this non-empty match.
          while (emptiesSkipped > 0) {
            result.push('');
            emptiesSkipped -= 1;
          }
        }
        result.push(m.substring(last, m.start()));
        last = m.end();
      }
      if (limit === 0 && last !== m.inputLength()) {
        // Unlimited match, no more delimiters but we have a non-empty input at the end. Catch up any skipped empty
        // matches, then emit the final match.
        while (emptiesSkipped > 0) {
          result.push('');
          emptiesSkipped -= 1;
        }
        result.push(m.substring(last, m.inputLength()));
      }
      if (limit !== 0 || result.length === 0) {
        result.push(m.substring(last, m.inputLength()));
      }
      return result;
    }

    /**
     *
     * @returns {string}
     */
    toString() {
      return this.patternInput;
    }

    /**
     * Returns the number of capturing groups in this matcher's pattern. Group zero denotes the entire
     * pattern and is excluded from this count.
     *
     * @returns {number} the number of capturing groups in this pattern
     */
    groupCount() {
      return this.re2Input.numberOfCapturingGroups();
    }

    /**
     * Return a map of the capturing groups in this matcher's pattern, where key is the name and value
     * is the index of the group in the pattern.
     * @returns {*}
     */
    namedGroups() {
      return this.re2Input.namedGroups;
    }

    /**
     *
     * @param {*} other
     * @returns {boolean}
     */
    equals(other) {
      if (this === other) {
        return true;
      }
      if (other === null || this.constructor !== other.constructor) {
        return false;
      }
      return this.flagsInput === other.flagsInput && this.patternInput === other.patternInput;
    }
  }

  exports.RE2JS = RE2JS;
  exports.RE2JSCompileException = RE2JSCompileException;
  exports.RE2JSException = RE2JSException;
  exports.RE2JSFlagsException = RE2JSFlagsException;
  exports.RE2JSGroupException = RE2JSGroupException;
  exports.RE2JSSyntaxException = RE2JSSyntaxException;

}));
//# sourceMappingURL=index.umd.js.map