/*!
 * regjsgen 0.8.0
 * Copyright 2014-2023 Benjamin Tan 
 * Available under the MIT license 
 */
;(function() {
  'use strict';
  // Used to determine if values are of the language type `Object`.
  var objectTypes = {
    'function': true,
    'object': true
  };
  // Used as a reference to the global object.
  var root = (objectTypes[typeof window] && window) || this;
  // Detect free variable `exports`.
  var freeExports = objectTypes[typeof exports] && exports && !exports.nodeType && exports;
  // Detect free variable `module`.
  var hasFreeModule = objectTypes[typeof module] && module && !module.nodeType;
  // Detect free variable `global` from Node.js or Browserified code and use it as `root`.
  var freeGlobal = freeExports && hasFreeModule && typeof global == 'object' && global;
  if (freeGlobal && (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal || freeGlobal.self === freeGlobal)) {
    root = freeGlobal;
  }
  // Used to check objects for own properties.
  var hasOwnProperty = Object.prototype.hasOwnProperty;
  /*--------------------------------------------------------------------------*/
  // Generates a string based on the given code point.
  // Based on https://mths.be/fromcodepoint by @mathias.
  function fromCodePoint() {
    var codePoint = Number(arguments[0]);
    if (
      !isFinite(codePoint) || // `NaN`, `+Infinity`, or `-Infinity`
      codePoint < 0 || // not a valid Unicode code point
      codePoint > 0x10FFFF || // not a valid Unicode code point
      Math.floor(codePoint) != codePoint // not an integer
    ) {
      throw RangeError('Invalid code point: ' + codePoint);
    }
    if (codePoint <= 0xFFFF) {
      // BMP code point
      return String.fromCharCode(codePoint);
    } else {
      // Astral code point; split in surrogate halves
      // http://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae
      codePoint -= 0x10000;
      var highSurrogate = (codePoint >> 10) + 0xD800;
      var lowSurrogate = (codePoint % 0x400) + 0xDC00;
      return String.fromCharCode(highSurrogate, lowSurrogate);
    }
  }
  /*--------------------------------------------------------------------------*/
  // Ensures that nodes have the correct types.
  var assertTypeRegexMap = {};
  function assertType(type, expected) {
    if (expected.indexOf('|') == -1) {
      if (type == expected) {
        return;
      }
      throw Error('Invalid node type: ' + type + '; expected type: ' + expected);
    }
    expected = hasOwnProperty.call(assertTypeRegexMap, expected)
      ? assertTypeRegexMap[expected]
      : (assertTypeRegexMap[expected] = RegExp('^(?:' + expected + ')$'));
    if (expected.test(type)) {
      return;
    }
    throw Error('Invalid node type: ' + type + '; expected types: ' + expected);
  }
  /*--------------------------------------------------------------------------*/
  // Generates a regular expression string based on an AST.
  function generate(node) {
    var type = node.type;
    if (hasOwnProperty.call(generators, type)) {
      return generators[type](node);
    }
    throw Error('Invalid node type: ' + type);
  }
  // Constructs a string by concatentating the output of each term.
  function generateSequence(generator, terms, /* optional */  separator) {
    var i = -1,
        length = terms.length,
        result = '',
        term;
    while (++i < length) {
      term = terms[i];
      if (separator && i > 0) result += separator;
      // Ensure that `\0` null escapes followed by number symbols are not
      // treated as backreferences.
      if (
        i + 1 < length &&
        terms[i].type == 'value' &&
        terms[i].kind == 'null' &&
        terms[i + 1].type == 'value' &&
        terms[i + 1].kind == 'symbol' &&
        terms[i + 1].codePoint >= 48 &&
        terms[i + 1].codePoint <= 57
      ) {
        result += '\\000';
        continue;
      }
      result += generator(term);
    }
    return result;
  }
  /*--------------------------------------------------------------------------*/
  function generateAlternative(node) {
    assertType(node.type, 'alternative');
    return generateSequence(generateTerm, node.body);
  }
  function generateAnchor(node) {
    assertType(node.type, 'anchor');
    switch (node.kind) {
      case 'start':
        return '^';
      case 'end':
        return '$';
      case 'boundary':
        return '\\b';
      case 'not-boundary':
        return '\\B';
      default:
        throw Error('Invalid assertion');
    }
  }
  var atomType = 'anchor|characterClass|characterClassEscape|dot|group|reference|unicodePropertyEscape|value';
  function generateAtom(node) {
    assertType(node.type, atomType);
    return generate(node);
  }
  function generateCharacterClass(node) {
    assertType(node.type, 'characterClass');
    var kind = node.kind;
    var separator = kind === 'intersection' ? '&&' : kind === 'subtraction' ? '--' : '';
    return '[' +
      (node.negative ? '^' : '') +
      generateSequence(generateClassAtom, node.body, separator) +
    ']';
  }
  function generateCharacterClassEscape(node) {
    assertType(node.type, 'characterClassEscape');
    return '\\' + node.value;
  }
  function generateCharacterClassRange(node) {
    assertType(node.type, 'characterClassRange');
    var min = node.min,
        max = node.max;
    if (min.type == 'characterClassRange' || max.type == 'characterClassRange') {
      throw Error('Invalid character class range');
    }
    return generateClassAtom(min) + '-' + generateClassAtom(max);
  }
  function generateClassAtom(node) {
    assertType(node.type, 'anchor|characterClass|characterClassEscape|characterClassRange|dot|value|unicodePropertyEscape|classStrings');
    return generate(node);
  }
  function generateClassStrings(node) {
    assertType(node.type, 'classStrings');
    return '\\q{' + generateSequence(generateClassString, node.strings, '|') + '}';
  }
  function generateClassString(node) {
    assertType(node.type, 'classString');
    return generateSequence(generate, node.characters);
  }
  function generateDisjunction(node) {
    assertType(node.type, 'disjunction');
    return generateSequence(generate, node.body, '|');
  }
  function generateDot(node) {
    assertType(node.type, 'dot');
    return '.';
  }
  function generateGroup(node) {
    assertType(node.type, 'group');
    var result = '';
    switch (node.behavior) {
      case 'normal':
        if (node.name) {
          result += '?<' + generateIdentifier(node.name) + '>';
        }
        break;
      case 'ignore':
        if (node.modifierFlags) {
          result += '?';
          if (node.modifierFlags.enabling) result += node.modifierFlags.enabling;
          if (node.modifierFlags.disabling) result += "-" + node.modifierFlags.disabling;
          result += ':';
        } else {
          result += '?:';
        }
        break;
      case 'lookahead':
        result += '?=';
        break;
      case 'negativeLookahead':
        result += '?!';
        break;
      case 'lookbehind':
        result += '?<=';
        break;
      case 'negativeLookbehind':
        result += '?';
    }
    throw new Error('Unknown reference type');
  }
  function generateTerm(node) {
    assertType(node.type, atomType + '|empty|quantifier');
    return generate(node);
  }
  function generateUnicodePropertyEscape(node) {
    assertType(node.type, 'unicodePropertyEscape');
    return '\\' + (node.negative ? 'P' : 'p') + '{' + node.value + '}';
  }
  function generateValue(node) {
    assertType(node.type, 'value');
    var kind = node.kind,
        codePoint = node.codePoint;
    if (typeof codePoint != 'number') {
      throw new Error('Invalid code point: ' + codePoint);
    }
    switch (kind) {
      case 'controlLetter':
        return '\\c' + fromCodePoint(codePoint + 64);
      case 'hexadecimalEscape':
        return '\\x' + ('00' + codePoint.toString(16).toUpperCase()).slice(-2);
      case 'identifier':
        return '\\' + fromCodePoint(codePoint);
      case 'null':
        return '\\' + codePoint;
      case 'octal':
        return '\\' + ('000' + codePoint.toString(8)).slice(-3);
      case 'singleEscape':
        switch (codePoint) {
          case 0x0008:
            return '\\b';
          case 0x0009:
            return '\\t';
          case 0x000A:
            return '\\n';
          case 0x000B:
            return '\\v';
          case 0x000C:
            return '\\f';
          case 0x000D:
            return '\\r';
          case 0x002D:
            return '\\-';
          default:
            throw Error('Invalid code point: ' + codePoint);
        }
      case 'symbol':
        return fromCodePoint(codePoint);
      case 'unicodeEscape':
        return '\\u' + ('0000' + codePoint.toString(16).toUpperCase()).slice(-4);
      case 'unicodeCodePointEscape':
        return '\\u{' + codePoint.toString(16).toUpperCase() + '}';
      default:
        throw Error('Unsupported node kind: ' + kind);
    }
  }
  /*--------------------------------------------------------------------------*/
  // Used to generate strings for each node type.
  var generators = {
    'alternative': generateAlternative,
    'anchor': generateAnchor,
    'characterClass': generateCharacterClass,
    'characterClassEscape': generateCharacterClassEscape,
    'characterClassRange': generateCharacterClassRange,
    'classStrings': generateClassStrings,
    'disjunction': generateDisjunction,
    'dot': generateDot,
    'group': generateGroup,
    'quantifier': generateQuantifier,
    'reference': generateReference,
    'unicodePropertyEscape': generateUnicodePropertyEscape,
    'value': generateValue
  };
  /*--------------------------------------------------------------------------*/
  // Export regjsgen.
  var regjsgen = {
    'generate': generate
  };
  // Some AMD build optimizers, like r.js, check for condition patterns like the following:
  if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {
    // Define as an anonymous module so it can be aliased through path mapping.
    define(function() {
      return regjsgen;
    });
    root.regjsgen = regjsgen;
  }
  // Check for `exports` after `define` in case a build optimizer adds an `exports` object.
  else if (freeExports && hasFreeModule) {
    // Export for CommonJS support.
    freeExports.generate = generate;
  }
  else {
    // Export to the global object.
    root.regjsgen = regjsgen;
  }
}.call(this));