Beispiel #1
0
        private void Init(string pattern, RegexOptions options, TimeSpan matchTimeout, CultureInfo culture)
        {
            ValidatePattern(pattern);
            ValidateOptions(options);
            ValidateMatchTimeout(matchTimeout);

            this.pattern         = pattern;
            internalMatchTimeout = matchTimeout;
            roptions             = options;

            // Parse the input
            RegexTree tree = RegexParser.Parse(pattern, roptions, culture);

            // Generate the RegexCode from the node tree.  This is required for interpreting,
            // and is used as input into RegexOptions.Compiled and RegexOptions.NonBacktracking.
            _code = RegexWriter.Write(tree, culture);

            if ((options & RegexOptions.NonBacktracking) != 0)
            {
                // NonBacktracking doesn't support captures (other than the implicit top-level capture).
                capnames = null;
                capslist = null;
                caps     = null;
                capsize  = 1;
            }
            else
            {
                capnames = tree.CapNames;
                capslist = tree.CapsList;
                caps     = _code.Caps;
                capsize  = _code.CapSize;
            }
        }
        public Regex(string pattern, RegexOptions options)
        {
            this.refsInitialized = false;
            if (pattern == null)
            {
                throw new ArgumentNullException();
            }
            if ((options < RegexOptions.None) || ((((int)options) >> 9) != 0))
            {
                throw new ArgumentOutOfRangeException();
            }
            if (((options & RegexOptions.ECMAScript) != RegexOptions.None) && ((options & ~(RegexOptions.CultureInvariant | RegexOptions.ECMAScript | RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.IgnoreCase)) != RegexOptions.None))
            {
                throw new ArgumentOutOfRangeException();
            }
            string text1 = options + ":" + pattern;

            this.pattern  = pattern;
            this.roptions = options;
            RegexTree t = RegexParser.Parse(pattern, this.roptions);

            this.capnames = t._capnames;
            this.capslist = t._capslist;
            this.code     = RegexWriter.Write(t);
            this.caps     = this.code._caps;
            this.capsize  = this.code._capsize;
        }
Beispiel #3
0
        /// <summary>Initializes the instance.</summary>
        /// <remarks>
        /// This is separated out of the constructor so that an app only using 'new Regex(pattern)'
        /// rather than 'new Regex(pattern, options)' can avoid statically referencing the Regex
        /// compiler, such that a tree shaker / linker can trim it away if it's not otherwise used.
        /// </remarks>
        private void Init(string pattern, RegexOptions options, TimeSpan matchTimeout, CultureInfo?culture)
        {
            ValidatePattern(pattern);
            ValidateOptions(options);
            ValidateMatchTimeout(matchTimeout);

            this.pattern         = pattern;
            roptions             = options;
            internalMatchTimeout = matchTimeout;

#if DEBUG
            if (IsDebug)
            {
                Debug.WriteLine($"Pattern: {pattern}    Options: {options & ~RegexOptions.Debug}    Timeout: {(matchTimeout == InfiniteMatchTimeout ? "infinite" : matchTimeout.ToString())}");
            }
#endif

            // Parse the input
            RegexTree tree = RegexParser.Parse(pattern, roptions, culture ?? ((options & RegexOptions.CultureInvariant) != 0 ? CultureInfo.InvariantCulture : CultureInfo.CurrentCulture));

            // Extract the relevant information
            capnames = tree.CapNames;
            capslist = tree.CapsList;
            _code    = RegexWriter.Write(tree);
            caps     = _code.Caps;
            capsize  = _code.CapSize;

            InitializeReferences();
        }
Beispiel #4
0
 public RegexInterpreterFactory(RegexTree tree)
 {
     // We use the CultureInfo field from the tree's culture which will only be set to an actual culture if the
     // tree contains IgnoreCase backreferences. If the tree doesn't have IgnoreCase backreferences, then we keep _culture as null.
     _culture = tree.Culture;
     // Generate and store the RegexInterpretedCode for the RegexTree and the specified culture
     _code = RegexWriter.Write(tree);
 }
Beispiel #5
0
        // This is the only function that should be called from outside.
        // It takes a RegexTree and creates a corresponding RegexCode.
        internal static RegexCode Write(RegexTree t) {
            RegexWriter w = new RegexWriter();
            RegexCode retval = w.RegexCodeFromRegexTree(t);
#if DBG
            if (t.Debug) {
                retval.Dump();
            }
#endif
            return retval;
        }
Beispiel #6
0
        /*
         * This is the only function that should be called from outside.
         * It takes a RegexTree and creates a corresponding RegexCode.
         */
        internal static RegexCode Write(RegexTree t)
        {
            RegexWriter w      = new RegexWriter();
            RegexCode   retval = w.RegexCodeFromRegexTree(t);

#if DBG
            if (t.Debug)
            {
                retval.Dump();
            }
#endif
            return(retval);
        }
Beispiel #7
0
        /// <summary>
        /// This is the only function that should be called from outside.
        /// It takes a RegexTree and creates a corresponding RegexCode.
        /// </summary>
        internal static RegexCode Write(RegexTree t)
        {
            Span <int> emittedSpan  = stackalloc int[EmittedSize];
            Span <int> intStackSpan = stackalloc int[IntStackSize];
            var        w            = new RegexWriter(emittedSpan, intStackSpan);

            RegexCode retval = w.RegexCodeFromRegexTree(t);

#if DEBUG
            if (t.Debug)
            {
                t.Dump();
                retval.Dump();
            }
#endif
            return(retval);
        }
Beispiel #8
0
        /// <summary>
        /// This is the only function that should be called from outside.
        /// It takes a RegexTree and creates a corresponding RegexCode.
        /// </summary>
        public static RegexCode Write(RegexTree tree)
        {
            Span <int> emittedSpan  = stackalloc int[EmittedSize];
            Span <int> intStackSpan = stackalloc int[IntStackSize];

            var       writer = new RegexWriter(emittedSpan, intStackSpan);
            RegexCode code   = writer.RegexCodeFromRegexTree(tree);

            writer.Dispose();

#if DEBUG
            if (tree.Debug)
            {
                tree.Dump();
                code.Dump();
            }
#endif

            return(code);
        }
Beispiel #9
0
        private void Init(string pattern, RegexOptions options, TimeSpan matchTimeout, CultureInfo?culture)
        {
            ValidatePattern(pattern);
            ValidateOptions(options);
            ValidateMatchTimeout(matchTimeout);

            this.pattern         = pattern;
            internalMatchTimeout = matchTimeout;
            roptions             = options;
            culture ??= GetTargetCulture(options);

#if DEBUG
            if (IsDebug)
            {
                Debug.WriteLine($"Pattern: {pattern}    Options: {options & ~RegexOptions.Debug}    Timeout: {(matchTimeout == InfiniteMatchTimeout ? "infinite" : matchTimeout.ToString())}");
            }
#endif

            // Parse the input
            RegexTree tree = RegexParser.Parse(pattern, roptions, culture);

            // Generate the RegexCode from the node tree.  This is required for interpreting,
            // and is used as input into RegexOptions.Compiled and RegexOptions.NonBacktracking.
            _code = RegexWriter.Write(tree);

            if ((options & RegexOptions.NonBacktracking) != 0)
            {
                // NonBacktracking doesn't support captures (other than the implicit top-level capture).
                capnames = null;
                capslist = null;
                caps     = null;
                capsize  = 1;
            }
            else
            {
                capnames = tree.CapNames;
                capslist = tree.CapsList;
                caps     = _code.Caps;
                capsize  = _code.CapSize;
            }
        }
Beispiel #10
0
        /// <summary>Initializes the instance.</summary>
        /// <remarks>
        /// This is separated out of the constructor to allow the Regex ctor that doesn't
        /// take a RegexOptions to avoid rooting the regex compiler, such that it can be trimmed away.
        /// </remarks>
        private void Init(string pattern, RegexOptions options, TimeSpan matchTimeout, CultureInfo?culture)
        {
            ValidatePattern(pattern);
            ValidateOptions(options);
            ValidateMatchTimeout(matchTimeout);

            this.pattern         = pattern;
            roptions             = options;
            internalMatchTimeout = matchTimeout;

            // Parse the input
            RegexTree tree = RegexParser.Parse(pattern, roptions, culture ?? ((options & RegexOptions.CultureInvariant) != 0 ? CultureInfo.InvariantCulture : CultureInfo.CurrentCulture));

            // Extract the relevant information
            capnames = tree.CapNames;
            capslist = tree.CapsList;
            _code    = RegexWriter.Write(tree);
            caps     = _code.Caps;
            capsize  = _code.CapSize;

            InitializeReferences();
        }
Beispiel #11
0
        private void Init(string pattern, RegexOptions options, TimeSpan matchTimeout, CultureInfo culture)
        {
            ValidatePattern(pattern);
            ValidateOptions(options);
            ValidateMatchTimeout(matchTimeout);

            this.pattern         = pattern;
            internalMatchTimeout = matchTimeout;
            roptions             = options;

            // Parse the input
            RegexTree tree = RegexParser.Parse(pattern, roptions, culture);

            // Generate the RegexCode from the node tree.  This is required for interpreting,
            // and is used as input into RegexOptions.Compiled and RegexOptions.NonBacktracking.
            _code = RegexWriter.Write(tree, culture);

            capnames = tree.CapNames;
            capslist = tree.CapsList;
            caps     = _code.Caps;
            capsize  = _code.CapSize;
        }
Beispiel #12
0
        /// <summary>Initializes the instance.</summary>
        /// <remarks>
        /// This is separated out of the constructor so that an app only using 'new Regex(pattern)'
        /// rather than 'new Regex(pattern, options)' can avoid statically referencing the Regex
        /// compiler, such that a tree shaker / linker can trim it away if it's not otherwise used.
        /// </remarks>
        private void Init(string pattern, RegexOptions options, TimeSpan matchTimeout, CultureInfo?culture)
        {
            ValidatePattern(pattern);
            ValidateOptions(options);
            ValidateMatchTimeout(matchTimeout);

            this.pattern         = pattern;
            roptions             = options;
            internalMatchTimeout = matchTimeout;

#if DEBUG
            if (Debug)
            {
                System.Diagnostics.Debug.Write($"Pattern:     {pattern}");
                RegexOptions displayOptions = options & ~RegexOptions.Debug;
                if (displayOptions != RegexOptions.None)
                {
                    System.Diagnostics.Debug.Write($"Options:     {displayOptions}");
                }
                if (matchTimeout != Regex.InfiniteMatchTimeout)
                {
                    System.Diagnostics.Debug.Write($"Timeout:     {matchTimeout}");
                }
            }
#endif

            // Parse the input
            RegexTree tree = RegexParser.Parse(pattern, roptions, culture ?? ((options & RegexOptions.CultureInvariant) != 0 ? CultureInfo.InvariantCulture : CultureInfo.CurrentCulture));

            // Extract the relevant information
            capnames = tree.CapNames;
            capslist = tree.CapsList;
            _code    = RegexWriter.Write(tree);
            caps     = _code.Caps;
            capsize  = _code.CapSize;

            InitializeReferences();
        }
Beispiel #13
0
        internal static RegexCode Write(RegexTree t)
        {
            RegexWriter writer = new RegexWriter();

            return(writer.RegexCodeFromRegexTree(t));
        }
Beispiel #14
0
        private Regex(string pattern, RegexOptions options, bool useCache)
        {
            CachedCodeEntry cachedAndUpdate = null;
            string          str             = null;

            if (pattern == null)
            {
                throw new ArgumentNullException("pattern");
            }
            if ((options < RegexOptions.None) || ((((int)options) >> 10) != 0))
            {
                throw new ArgumentOutOfRangeException("options");
            }
            if (((options & RegexOptions.ECMAScript) != RegexOptions.None) && ((options & ~(RegexOptions.CultureInvariant | RegexOptions.ECMAScript | RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.IgnoreCase)) != RegexOptions.None))
            {
                throw new ArgumentOutOfRangeException("options");
            }
            if ((options & RegexOptions.CultureInvariant) != RegexOptions.None)
            {
                str = CultureInfo.InvariantCulture.ToString();
            }
            else
            {
                str = CultureInfo.CurrentCulture.ToString();
            }
            string[] strArray = new string[] { ((int)options).ToString(NumberFormatInfo.InvariantInfo), ":", str, ":", pattern };
            string   key      = string.Concat(strArray);

            cachedAndUpdate = LookupCachedAndUpdate(key);
            this.pattern    = pattern;
            this.roptions   = options;
            if (cachedAndUpdate == null)
            {
                RegexTree t = RegexParser.Parse(pattern, this.roptions);
                this.capnames = t._capnames;
                this.capslist = t._capslist;
                this.code     = RegexWriter.Write(t);
                this.caps     = this.code._caps;
                this.capsize  = this.code._capsize;
                this.InitializeReferences();
                t = null;
                if (useCache)
                {
                    cachedAndUpdate = this.CacheCode(key);
                }
            }
            else
            {
                this.caps            = cachedAndUpdate._caps;
                this.capnames        = cachedAndUpdate._capnames;
                this.capslist        = cachedAndUpdate._capslist;
                this.capsize         = cachedAndUpdate._capsize;
                this.code            = cachedAndUpdate._code;
                this.factory         = cachedAndUpdate._factory;
                this.runnerref       = cachedAndUpdate._runnerref;
                this.replref         = cachedAndUpdate._replref;
                this.refsInitialized = true;
            }
            if (this.UseOptionC() && (this.factory == null))
            {
                this.factory = this.Compile(this.code, this.roptions);
                if (useCache && (cachedAndUpdate != null))
                {
                    cachedAndUpdate.AddCompiled(this.factory);
                }
                this.code = null;
            }
        }
Beispiel #15
0
        private Regex(string pattern, RegexOptions options, TimeSpan matchTimeout, bool addToCache)
        {
            if (pattern == null)
            {
                throw new ArgumentNullException(nameof(pattern));
            }

            if (options < RegexOptions.None || (((int)options) >> MaxOptionShift) != 0)
            {
                throw new ArgumentOutOfRangeException(nameof(options));
            }

            if ((options & RegexOptions.ECMAScript) != 0 &&
                (options & ~(RegexOptions.ECMAScript |
                             RegexOptions.IgnoreCase |
                             RegexOptions.Multiline |
                             RegexOptions.Compiled |
                             RegexOptions.CultureInvariant
#if DEBUG
                             | RegexOptions.Debug
#endif
                             )) != 0)
            {
                throw new ArgumentOutOfRangeException(nameof(options));
            }

            ValidateMatchTimeout(matchTimeout);

            // After parameter validation assign
            this.pattern         = pattern;
            roptions             = options;
            internalMatchTimeout = matchTimeout;

            // Cache handling. Try to look up this regex in the cache.
            CultureInfo culture = (options & RegexOptions.CultureInvariant) != 0 ?
                                  CultureInfo.InvariantCulture :
                                  CultureInfo.CurrentCulture;
            var             key    = new CachedCodeEntryKey(options, culture.ToString(), pattern);
            CachedCodeEntry cached = GetCachedCode(key, false);

            if (cached == null)
            {
                // Parse the input
                RegexTree tree = RegexParser.Parse(pattern, roptions, culture);

                // Extract the relevant information
                capnames = tree.CapNames;
                capslist = tree.CapsList;
                _code    = RegexWriter.Write(tree);
                caps     = _code.Caps;
                capsize  = _code.CapSize;

                InitializeReferences();

                tree = null;
                if (addToCache)
                {
                    cached = GetCachedCode(key, true);
                }
            }
            else
            {
                caps     = cached.Caps;
                capnames = cached.Capnames;
                capslist = cached.Capslist;
                capsize  = cached.Capsize;
                _code    = cached.Code;
#if FEATURE_COMPILED
                factory = cached.Factory;
#endif

                // Cache runner and replacement
                _runnerref       = cached.Runnerref;
                _replref         = cached.ReplRef;
                _refsInitialized = true;
            }

#if FEATURE_COMPILED
            // if the compile option is set, then compile the code if it's not already
            if (UseOptionC() && factory == null)
            {
                factory = Compile(_code, roptions);

                if (addToCache && cached != null)
                {
                    cached.AddCompiled(factory);
                }

                _code = null;
            }
#endif
        }
Beispiel #16
0
        private Regex(String pattern, RegexOptions options, TimeSpan matchTimeout, bool useCache)
        {
            RegexTree       tree;
            CachedCodeEntry cached     = null;
            string          cultureKey = null;

            if (pattern == null)
            {
                throw new ArgumentNullException(nameof(pattern));
            }
            if (options < RegexOptions.None || (((int)options) >> MaxOptionShift) != 0)
            {
                throw new ArgumentOutOfRangeException(nameof(options));
            }
            if ((options & RegexOptions.ECMAScript) != 0 &&
                (options & ~(RegexOptions.ECMAScript |
                             RegexOptions.IgnoreCase |
                             RegexOptions.Multiline |
                             RegexOptions.CultureInvariant
#if DEBUG
                             | RegexOptions.Debug
#endif
                             )) != 0)
            {
                throw new ArgumentOutOfRangeException(nameof(options));
            }

            ValidateMatchTimeout(matchTimeout);

            // Try to look up this regex in the cache.  We do this regardless of whether useCache is true since there's
            // really no reason not to.
            if ((options & RegexOptions.CultureInvariant) != 0)
            {
                cultureKey = CultureInfo.InvariantCulture.ToString(); // "English (United States)"
            }
            else
            {
                cultureKey = CultureInfo.CurrentCulture.ToString();
            }

            var key = new CachedCodeEntryKey(options, cultureKey, pattern);
            cached = LookupCachedAndUpdate(key);

            this.pattern = pattern;
            roptions     = options;

            internalMatchTimeout = matchTimeout;

            if (cached == null)
            {
                // Parse the input
                tree = RegexParser.Parse(pattern, roptions);

                // Extract the relevant information
                _capnames = tree._capnames;
                capslist  = tree._capslist;
                _code     = RegexWriter.Write(tree);
                _caps     = _code._caps;
                capsize   = _code._capsize;

                InitializeReferences();

                tree = null;
                if (useCache)
                {
                    cached = CacheCode(key);
                }
            }
            else
            {
                _caps            = cached._caps;
                _capnames        = cached._capnames;
                capslist         = cached._capslist;
                capsize          = cached._capsize;
                _code            = cached._code;
                _runnerref       = cached._runnerref;
                _replref         = cached._replref;
                _refsInitialized = true;
            }
        }
Beispiel #17
0
 internal static RegexCode Write(RegexTree t)
 {
     RegexWriter writer = new RegexWriter();
     return writer.RegexCodeFromRegexTree(t);
 }
Beispiel #18
0
        /// <summary>
        /// The top level RegexCode generator. It does a depth-first walk
        /// through the tree and calls EmitFragment to emits code before
        /// and after each child of an interior node, and at each leaf.
        /// </summary>
        public RegexCode RegexCodeFromRegexTree(RegexTree tree)
        {
            Span <int>  emittedSpan  = stackalloc int[EmittedSize];
            Span <int>  intStackSpan = stackalloc int[IntStackSize];
            RegexWriter writer       = new RegexWriter(emittedSpan, intStackSpan);

            // construct sparse capnum mapping if some numbers are unused
            int capsize;

            if (tree._capnumlist == null || tree._captop == tree._capnumlist.Length)
            {
                capsize      = tree._captop;
                writer._caps = null;
            }
            else
            {
                capsize      = tree._capnumlist.Length;
                writer._caps = tree._caps;
                for (int i = 0; i < tree._capnumlist.Length; i++)
                {
                    writer._caps[tree._capnumlist[i]] = i;
                }
            }

            RegexNode curNode  = tree._root;
            int       curChild = 0;

            writer.Emit(RegexCode.Lazybranch, 0);

            for (; ;)
            {
                if (curNode._children == null)
                {
                    writer.EmitFragment(curNode._type, curNode, 0);
                }
                else if (curChild < curNode._children.Count)
                {
                    writer.EmitFragment(curNode._type | BeforeChild, curNode, curChild);

                    curNode = curNode._children[curChild];
                    writer._intStack.Append(curChild);
                    curChild = 0;
                    continue;
                }

                if (writer._intStack.Length == 0)
                {
                    break;
                }

                curChild = writer._intStack.Pop();
                curNode  = curNode._next;

                writer.EmitFragment(curNode._type | AfterChild, curNode, curChild);
                curChild++;
            }

            writer.PatchJump(0, writer._emitted.Length);
            writer.Emit(RegexCode.Stop);

            RegexPrefix fcPrefix = RegexFCD.FirstChars(tree);
            RegexPrefix prefix   = RegexFCD.Prefix(tree);
            bool        rtl      = ((tree._options & RegexOptions.RightToLeft) != 0);

            CultureInfo     culture = (tree._options & RegexOptions.CultureInvariant) != 0 ? CultureInfo.InvariantCulture : CultureInfo.CurrentCulture;
            RegexBoyerMoore bmPrefix;

            if (prefix != null && prefix.Prefix.Length > 0)
            {
                bmPrefix = new RegexBoyerMoore(prefix.Prefix, prefix.CaseInsensitive, rtl, culture);
            }
            else
            {
                bmPrefix = null;
            }

            int anchors = RegexFCD.Anchors(tree);

            int[] emitted = writer._emitted.AsReadOnlySpan().ToArray();

            // Cleaning up and returning the borrowed arrays
            writer._emitted.Dispose();
            writer._intStack.Dispose();

            return(new RegexCode(emitted, writer._stringTable, writer._trackCount, writer._caps, capsize, bmPrefix, fcPrefix, anchors, rtl));
        }
        private Regex(String pattern, RegexOptions options, bool useCache)
        {
            RegexTree       tree;
            CachedCodeEntry cached     = null;
            string          cultureKey = null;

            if (pattern == null)
            {
                throw new ArgumentNullException("pattern");
            }
            if (options < RegexOptions.None || (((int)options) >> MaxOptionShift) != 0)
            {
                throw new ArgumentOutOfRangeException("options");
            }
            if ((options & RegexOptions.ECMAScript) != 0 &&
                (options & ~(RegexOptions.ECMAScript |
                             RegexOptions.IgnoreCase |
                             RegexOptions.Multiline |
                             RegexOptions.Compiled |
                             RegexOptions.CultureInvariant
#if DBG
                             | RegexOptions.Debug
#endif
                             )) != 0)
            {
                throw new ArgumentOutOfRangeException("options");
            }

            // Try to look up this regex in the cache.  We do this regardless of whether useCache is true since there's
            // really no reason not to.
            if ((options & RegexOptions.CultureInvariant) != 0)
            {
                cultureKey = CultureInfo.InvariantCulture.ThreeLetterWindowsLanguageName;
            }
            else
            {
                cultureKey = CultureInfo.CurrentCulture.ThreeLetterWindowsLanguageName;
            }

            String key = ((int)options).ToString(NumberFormatInfo.InvariantInfo) + ":" + cultureKey + ":" + pattern;
            cached = LookupCachedAndUpdate(key);

            this.pattern  = pattern;
            this.roptions = options;

            if (cached == null)
            {
                // Parse the input
                tree = RegexParser.Parse(pattern, roptions);

                // Extract the relevant information
                capnames = tree._capnames;
                capslist = tree._capslist;
                code     = RegexWriter.Write(tree);
                caps     = code._caps;
                capsize  = code._capsize;

                InitializeReferences();

                tree = null;
                if (useCache)
                {
                    cached = CacheCode(key);
                }
            }
            else
            {
                caps            = cached._caps;
                capnames        = cached._capnames;
                capslist        = cached._capslist;
                capsize         = cached._capsize;
                code            = cached._code;
                factory         = cached._factory;
                runnerref       = cached._runnerref;
                replref         = cached._replref;
                refsInitialized = true;
            }

            // if the compile option is set, then compile the code if it's not already
            if (UseOptionC() && factory == null)
            {
                factory = Compile(code, roptions);

                if (useCache && cached != null)
                {
                    cached.AddCompiled(factory);
                }
                code = null;
            }
        }
Beispiel #20
0
        // Returns a Regex object corresponding to the given pattern, compiled with
        // the specified options.
        //| <include file='doc\Regex.uex' path='docs/doc[@for="Regex.Regex1"]/*' />
        /// <devdoc>
        ///    <para>
        ///       Creates and compiles a regular expression object for the
        ///       specified regular expression
        ///       with options that modify the pattern.
        ///    </para>
        /// </devdoc>
        public Regex(String pattern, RegexOptions options)
        {
            RegexTree       tree;
            CachedCodeEntry cached;

            if (pattern == null)
            {
                throw new ArgumentNullException("pattern");
            }


            if (options < RegexOptions.None || (((int)options) >> MaxOptionShift) != 0)
            {
                throw new ArgumentOutOfRangeException("options");
            }
            if ((options & RegexOptions.ECMAScript) != 0 &&
                (options & ~(RegexOptions.ECMAScript | RegexOptions.IgnoreCase | RegexOptions.Multiline | RegexOptions.Compiled
#if DBG
                             | RegexOptions.Debug
#endif
                             )) != 0)
            {
                throw new ArgumentOutOfRangeException("options");
            }

            //XXX: String key = ((int) options).ToString(NumberFormatInfo.InvariantInfo) + ":" + pattern;
            String key = ((int)options).ToString() + ":" + pattern;

#if REGEX_USE_CACHE
            cached = LookupCached(key);
#else
            cached = null;
#endif
            this.pattern  = pattern;
            this.roptions = options;

            if (cached == null)
            {
                // Parse the input
                tree = RegexParser.Parse(pattern, roptions);

                // Extract the relevant information
                capnames = tree._capnames;
                capslist = tree._capslist;
                code     = RegexWriter.Write(tree);
                caps     = code._caps;
                capsize  = code._capsize;

                InitializeReferences();

                tree = null;
#if REGEX_USE_CACHE
                cachedentry = CacheCode(key);
#endif
            }
            else
            {
                caps     = cached._caps;
                capnames = cached._capnames;
                capslist = cached._capslist;
                capsize  = cached._capsize;
                code     = cached._code;
//                factory    = cached._factory;
                runnerref       = cached._runnerref;
                replref         = cached._replref;
                refsInitialized = true;

                cachedentry = cached;
            }
//
// Singularity does not support compilation of regular expressions
//          // if the compile option is set, then compile the code if it's not already
//          if (UseOptionC() && factory == null) {
//              factory = Compile(code, roptions);
//              cachedentry.AddCompiled(factory);
//              code = null;
//          }
//
        }