public static function toJS($regexp, $isGlobal = false)
	{
		$regexpInfo = RegexpParser::parse($regexp);
		$dotAll     = (strpos($regexpInfo['modifiers'], 's') !== false);

		$regexp = '';
		$pos = 0;

		foreach ($regexpInfo['tokens'] as $tok)
		{
			$regexp .= self::convertUnicodeCharacters(
				substr($regexpInfo['regexp'], $pos, $tok['pos'] - $pos),
				false,
				$dotAll
			);

			switch ($tok['type'])
			{
				case 'option':
					if ($tok['options'] !== 'J')
					{
						throw new RuntimeException('Regexp options are not supported');
					}
					break;

				case 'capturingSubpatternStart':
					$regexp .= '(';
					break;

				case 'nonCapturingSubpatternStart':
					if (!empty($tok['options']))
					{
						throw new RuntimeException('Subpattern options are not supported');
					}

					$regexp .= '(?:';
					break;

				case 'capturingSubpatternEnd':
				case 'nonCapturingSubpatternEnd':
					$regexp .= ')' . substr($tok['quantifiers'], 0, 1);
					break;

				case 'characterClass':
					$regexp .= '[';
					$regexp .= self::convertUnicodeCharacters($tok['content'], true, false);
					$regexp .= ']' . substr($tok['quantifiers'], 0, 1);
					break;

				case 'lookaheadAssertionStart':
					$regexp .= '(?=';
					break;

				case 'negativeLookaheadAssertionStart':
					$regexp .= '(?!';
					break;

				case 'lookaheadAssertionEnd':
				case 'negativeLookaheadAssertionEnd':
					$regexp .= ')';
					break;

				default:
					throw new RuntimeException("Unsupported token type '" . $tok['type'] . "'");
			}

			$pos = $tok['pos'] + $tok['len'];
		}

		$regexp .= self::convertUnicodeCharacters(substr($regexpInfo['regexp'], $pos), false, $dotAll);

		if ($regexpInfo['delimiter'] !== '/')
		{
			$regexp = preg_replace('#(?<!\\\\)((?:\\\\\\\\)*+)/#', '$1\\/', $regexp);
		}

		$modifiers = preg_replace('#[^im]#', '', $regexpInfo['modifiers']);
		if ($isGlobal)
		{
			$modifiers .= 'g';
		}

		if ($regexp === '')
		{
			$regexp = '(?:)';
		}

		return '/' . self::escapeLineTerminators($regexp) . '/' . $modifiers;
	}