📄 index.cjs.cjs
/home/palash/git/site/node_modules/re2js/build/index.cjs.cjs
Language: cjs • Lines: 5792
/*!
 * 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
 */
'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.cjs.cjs.map