• 给 C# 代码动态着色的 JavaScript 脚本



    脚本没有实现的功能: 没有给 "类、接口、结构、枚举、委托" 的名称着色, 因为名称太多了(373 K.)

    脚本和 VS2008 默认着色的不同: 所有预编译指令我给弄成灰色了.

    其他暂时没有发现(C#才学了一点), 如发现问题, 希望能告诉我.

    C# 代码着色脚本及使用方法:

    这是一个完整的测试页面:



    来个强测试, Net Regex.cs 源码(使用该脚本的着色效果):
    
    //------------------------------------------------------------------------------
    // 
    //     Copyright (c) Microsoft Corporation.  All rights reserved.
    //                                                                 
    //------------------------------------------------------------------------------
    
    // The Regex class represents a single compiled instance of a regular
    // expression.
    
    namespace System.Text.RegularExpressions {
    
        using System;
        using System.Threading;
        using System.Collections;
        using System.Runtime.Serialization;
        using System.Reflection;
        using System.Reflection.Emit;
        using System.Globalization;
        using System.Security.Policy;
        using System.Security.Permissions;
        using System.Runtime.CompilerServices;
        using System.Collections.Generic;
        using System.Runtime.Versioning;
        
        /// 
        ///    
        ///       Represents an immutable, compiled regular expression. Also
        ///       contains static methods that allow use of regular expressions without instantiating
        ///       a Regex explicitly.
        ///    
        /// 
        [ Serializable() ] 
        public class Regex : ISerializable {
    
            // Fields used by precompiled regexes
            protected internal string pattern;
            protected internal RegexRunnerFactory factory;       // if compiled, this is the RegexRunner subclass
            protected internal RegexOptions roptions;            // the top-level options from the options string
            protected internal Hashtable caps;                   // if captures are sparse, this is the hashtable capnum->index
            protected internal Hashtable capnames;               // if named captures are used, this maps names->index
            protected internal String[]  capslist;               // if captures are sparse or named captures are used, this is the sorted list of names
            protected internal int       capsize;                // the size of the capture array
    
            internal  ExclusiveReference runnerref;              // cached runner
            internal  SharedReference    replref;                // cached parsed replacement pattern
            internal  RegexCode          code;                   // if interpreted, this is the code for RegexIntepreter
            internal  bool refsInitialized = false;
    
            internal static LinkedList livecode = new LinkedList();// the cached of code and factories that are currently loaded
            internal static int cacheSize = 15;
            
            internal const int MaxOptionShift = 10;
    
            protected Regex() {
            }
    
            /*
             * Compiles and returns a Regex object corresponding to the given pattern
             */
            /// 
            ///    
            ///       Creates and compiles a regular expression object for the specified regular
            ///       expression.
            ///    
            /// 
            public Regex(String pattern) : this(pattern, RegexOptions.None, false) {
            }
    
            /*
             * Returns a Regex object corresponding to the given pattern, compiled with
             * the specified options.
             */
            /// 
            ///    
            ///       Creates and compiles a regular expression object for the
            ///       specified regular expression
            ///       with options that modify the pattern.
            ///    
            /// 
            public Regex(String pattern, RegexOptions options) : this(pattern, options, false){
            }
            
            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;
                }
            }
    
            /* 
             *  ISerializable constructor
             */
            protected Regex(SerializationInfo info, StreamingContext context) : this(info.GetString("pattern"), (RegexOptions) info.GetInt32("options")) {
            }
    
            /* 
             *  ISerializable method
             */
            /// 
            void ISerializable.GetObjectData(SerializationInfo si, StreamingContext context) {
                si.AddValue("pattern", this.ToString());
                si.AddValue("options", this.Options);
            }
    
            /* 
            * This method is here for perf reasons: if the call to RegexCompiler is NOT in the 
            * Regex constructor, we don't load RegexCompiler and its reflection classes when
            * instantiating a non-compiled regex
            * This method is internal virtual so the jit does not inline it.
            */
            [
                HostProtection(MayLeakOnAbort=true),
                MethodImplAttribute(MethodImplOptions.NoInlining)
            ]
            internal RegexRunnerFactory Compile(RegexCode code, RegexOptions roptions) {
                return RegexCompiler.Compile(code, roptions);
            }
    
            /*
             * Escape metacharacters within the string
             */
            /// 
            ///    
            ///       Escapes 
            ///          a minimal set of metacharacters (\, *, +, ?, |, {, [, (, ), ^, $, ., #, and
            ///          whitespace) by replacing them with their \ codes. This converts a string so that
            ///          it can be used as a constant within a regular expression safely. (Note that the
            ///          reason # and whitespace must be escaped is so the string can be used safely
            ///          within an expression parsed with x mode. If future Regex features add
            ///          additional metacharacters, developers should depend on Escape to escape those
            ///          characters as well.)
            ///       
            ///    
            public static String Escape(String str) {
                if (str==null)
                    throw new ArgumentNullException("str");
                
                return RegexParser.Escape(str);
            }
    
            /*
             * Unescape character codes within the string
             */
            /// 
            ///    
            ///       Unescapes any escaped characters in the input string.
            ///    
            /// 
            public static String Unescape(String str) {
                if (str==null)
                    throw new ArgumentNullException("str");
                
                return RegexParser.Unescape(str);
            }
    
            public static int CacheSize {
                get {
                    return cacheSize;
                }
                set {
                    if (value < 0)
                        throw new ArgumentOutOfRangeException("value");
    
                    cacheSize = value;
                    if (livecode.Count > cacheSize) {
                        lock (livecode) {
                            while (livecode.Count > cacheSize)
                                livecode.RemoveLast();
                        }
                    }
                }
            }
            
            /// 
            ///    
            ///       Returns the options passed into the constructor
            ///    
            /// 
            public RegexOptions Options {
                get { return roptions;}
            }
    
            /*
             * True if the regex is leftward
             */
            /// 
            ///    
            ///       Indicates whether the regular expression matches from right to
            ///       left.
            ///    
            /// 
            public bool RightToLeft {
                get {
                    return UseOptionR();
                }
            }
    
            /// 
            ///    
            ///       Returns the regular expression pattern passed into the constructor
            ///    
            /// 
            public override string ToString() {
                return pattern;
            }
    
            /*
             * Returns an array of the group names that are used to capture groups
             * in the regular expression. Only needed if the regex is not known until
             * runtime, and one wants to extract captured groups. (Probably unusual,
             * but supplied for completeness.)
             */
            /// 
            ///    Returns 
            ///       the GroupNameCollection for the regular expression. This collection contains the
            ///       set of strings used to name capturing groups in the expression. 
            ///    
            public String[] GetGroupNames() {
                String[] result;
    
                if (capslist == null) {
                    int max = capsize;
                    result = new String[max];
    
                    for (int i = 0; i < max; i++) {
                        result[i] = Convert.ToString(i, CultureInfo.InvariantCulture);
                    }
                }
                else {
                    result = new String[capslist.Length];
    
                    System.Array.Copy(capslist, 0, result, 0, capslist.Length);
                }
    
                return result;
            }
    
            /*
             * Returns an array of the group numbers that are used to capture groups
             * in the regular expression. Only needed if the regex is not known until
             * runtime, and one wants to extract captured groups. (Probably unusual,
             * but supplied for completeness.)
             */
            /// 
            ///    returns 
            ///       the integer group number corresponding to a group name. 
            ///    
            public int[] GetGroupNumbers() {
                int[] result;
    
                if (caps == null) {
                    int max = capsize;
                    result = new int[max];
    
                    for (int i = 0; i < max; i++) {
                        result[i] = i;
                    }
                }
                else {
                    result = new int[caps.Count];
    
                    IDictionaryEnumerator de = caps.GetEnumerator();
                    while (de.MoveNext()) {
                        result[(int)de.Value] = (int)de.Key;
                    }
                }
    
                return result;
            }
    
            /*
             * Given a group number, maps it to a group name. Note that nubmered
             * groups automatically get a group name that is the decimal string
             * equivalent of its number.
             *
             * Returns null if the number is not a recognized group number.
             */
            /// 
            ///    
            ///       Retrieves a group name that corresponds to a group number.
            ///    
            /// 
            public String GroupNameFromNumber(int i) {
                if (capslist == null) {
                    if (i >= 0 && i < capsize)
                        return i.ToString(CultureInfo.InvariantCulture);
    
                    return String.Empty;
                }
                else {
                    if (caps != null) {
                        Object obj = caps[i];
                        if (obj == null)
                            return String.Empty;
    
                        i = (int)obj;
                    }
    
                    if (i >= 0 && i < capslist.Length)
                        return capslist[i];
    
                    return String.Empty;
                }
            }
    
            /*
             * Given a group name, maps it to a group number. Note that nubmered
             * groups automatically get a group name that is the decimal string
             * equivalent of its number.
             *
             * Returns -1 if the name is not a recognized group name.
             */
            /// 
            ///    
            ///       Returns a group number that corresponds to a group name.
            ///    
            /// 
            public int GroupNumberFromName(String name) {
                int result = -1;
    
                if (name == null)
                    throw new ArgumentNullException("name");
    
                // look up name if we have a hashtable of names
                if (capnames != null) {
                    Object ret = capnames[name];
    
                    if (ret == null)
                        return -1;
    
                    return(int)ret;
                }
    
                // convert to an int if it looks like a number
                result = 0;
                for (int i = 0; i < name.Length; i++) {
                    char ch = name[i];
    
                    if (ch > '9' || ch < '0')
                        return -1;
    
                    result *= 10;
                    result += (ch - '0');
                }
    
                // return int if it's in range
                if (result >= 0 && result < capsize)
                    return result;
    
                return -1;
            }
    
            /*
             * Static version of simple IsMatch call
             */
            ///    
            ///       
            ///          Searches the input 
            ///             string for one or more occurrences of the text supplied in the pattern
            ///             parameter.
            ///       
            ///    
            public static bool IsMatch(String input, String pattern) {
                return new Regex(pattern, RegexOptions.None, true).IsMatch(input);
            }
    
            /*
             * Static version of simple IsMatch call
             */
            /// 
            ///    
            ///       Searches the input string for one or more occurrences of the text 
            ///          supplied in the pattern parameter with matching options supplied in the options
            ///          parameter.
            ///       
            ///    
            public static bool IsMatch(String input, String pattern, RegexOptions options) {
                return new Regex(pattern, options, true).IsMatch(input);
            }
    
            /*
             * Returns true if the regex finds a match within the specified string
             */
            /// 
            ///    
            ///       Searches the input string for one or 
            ///          more matches using the previous pattern, options, and starting
            ///          position.
            ///       
            ///    
            public bool IsMatch(String input) {
                if (input == null)
                    throw new ArgumentNullException("input");
    
                return(null == Run(true, -1, input, 0, input.Length, UseOptionR() ? input.Length : 0));
            }
    
            /*
             * Returns true if the regex finds a match after the specified position
             * (proceeding leftward if the regex is leftward and rightward otherwise)
             */
            /// 
            ///    
            ///       Searches the input 
            ///          string for one or more matches using the previous pattern and options, with
            ///          a new starting position.
            ///    
            /// 
            public bool IsMatch(String input, int startat) {
                if (input == null)
                    throw new ArgumentNullException("input");
    
                return(null == Run(true, -1, input, 0, input.Length, startat));
            }
    
            /*
             * Static version of simple Match call
             */
            ///    
            ///       
            ///          Searches the input string for one or more occurrences of the text 
            ///             supplied in the pattern parameter.
            ///       
            ///    
            public static Match Match(String input, String pattern) {
                return new Regex(pattern, RegexOptions.None, true).Match(input);
            }
    
            /*
             * Static version of simple Match call
             */
            /// 
            ///    
            ///       Searches the input string for one or more occurrences of the text 
            ///          supplied in the pattern parameter. Matching is modified with an option
            ///          string.
            ///       
            ///    
            public static Match Match(String input, String pattern, RegexOptions options) {
                return new Regex(pattern, options, true).Match(input);
            }
    
            /*
             * Finds the first match for the regular expression starting at the beginning
             * of the string (or at the end of the string if the regex is leftward)
             */
            /// 
            ///    
            ///       Matches a regular expression with a string and returns
            ///       the precise result as a RegexMatch object.
            ///    
            /// 
            public Match Match(String input) {
                if (input == null)
                    throw new ArgumentNullException("input");
    
                return Run(false, -1, input, 0, input.Length, UseOptionR() ? input.Length : 0);
            }
    
            /*
             * Finds the first match, starting at the specified position
             */
            /// 
            ///    Matches a regular expression with a string and returns
            ///    the precise result as a RegexMatch object.
            /// 
            public Match Match(String input, int startat) {
                if (input == null)
                    throw new ArgumentNullException("input");
    
                return Run(false, -1, input, 0, input.Length, startat);
            }
    
            /*
             * Finds the first match, restricting the search to the specified interval of
             * the char array.
             */
            /// 
            ///    
            ///       Matches a
            ///       regular expression with a string and returns the precise result as a
            ///       RegexMatch object.
            ///    
            /// 
            public Match Match(String input, int beginning, int length) {
                if (input == null)
                    throw new ArgumentNullException("input");
    
                return Run(false, -1, input, beginning, length, UseOptionR() ? beginning + length : beginning);
            }
    
            /*
             * Static version of simple Matches call
             */
            ///    
            ///       
            ///          Returns all the successful matches as if Match were
            ///          called iteratively numerous times.
            ///       
            ///    
            public static MatchCollection Matches(String input, String pattern) {
                return new Regex(pattern, RegexOptions.None, true).Matches(input);
            }
    
            /*
             * Static version of simple Matches call
             */
            /// 
            ///    
            ///       Returns all the successful matches as if Match were called iteratively
            ///       numerous times.
            ///    
            /// 
            public static MatchCollection Matches(String input, String pattern, RegexOptions options) {
                return new Regex(pattern, options, true).Matches(input);
            }
    
            /*
             * Finds the first match for the regular expression starting at the beginning
             * of the string Enumerator(or at the end of the string if the regex is leftward)
             */
            /// 
            ///    
            ///       Returns
            ///       all the successful matches as if Match was called iteratively numerous
            ///       times.
            ///    
            /// 
            public MatchCollection Matches(String input) {
                if (input == null)
                    throw new ArgumentNullException("input");
    
                return new MatchCollection(this, input, 0, input.Length, UseOptionR() ? input.Length : 0);
            }
    
            /*
             * Finds the first match, starting at the specified position
             */
            /// 
            ///    
            ///       Returns
            ///       all the successful matches as if Match was called iteratively numerous
            ///       times.
            ///    
            /// 
            public MatchCollection Matches(String input, int startat) {
                if (input == null)
                    throw new ArgumentNullException("input");
    
                return new MatchCollection(this, input, 0, input.Length, startat);
            }
    
            /*
             * Static version of simple Replace call
             */
            /// 
            ///    
            ///       Replaces 
            ///          all occurrences of the pattern with the  pattern, starting at
            ///          the first character in the input string. 
            ///       
            ///    
            public static String Replace(String input, String pattern, String replacement) {
                return new Regex(pattern, RegexOptions.None, true).Replace(input, replacement);
            }
    
            /*
             * Static version of simple Replace call
             */
            /// 
            ///    
            ///       Replaces all occurrences of 
            ///          the with the 
            ///          pattern, starting at the first character in the input string. 
            ///       
            ///    
            public static String Replace(String input, String pattern, String replacement, RegexOptions options) {
                return new Regex(pattern, options, true).Replace(input, replacement);
            }
    
            /*
             * Does the replacement
             */
            /// 
            ///    
            ///       Replaces all occurrences of 
            ///          the  with the  pattern, starting at the
            ///          first character in the input string, using the previous patten. 
            ///       
            ///    
            public String Replace(String input, String replacement) {
                if (input == null)
                    throw new ArgumentNullException("input");
    
                return Replace(input, replacement, -1, UseOptionR() ? input.Length : 0);
            }
    
            /*
             * Does the replacement
             */
            /// 
            ///    
            ///    Replaces all occurrences of the (previously defined) with the 
            ///     pattern, starting at the first character in the input string. 
            /// 
            /// 
            public String Replace(String input, String replacement, int count) {
                if (input == null)
                    throw new ArgumentNullException("input");
    
                return Replace(input, replacement, count, UseOptionR() ? input.Length : 0);
            }
    
            /*
             * Does the replacement
             */
            /// 
            ///    
            ///    Replaces all occurrences of the with the recent 
            ///     pattern, starting at the character position 
            ///    
            /// 
            /// 
            public String Replace(String input, String replacement, int count, int startat) {
                RegexReplacement repl;
    
                if (input == null)
                    throw new ArgumentNullException("input");
                if (replacement == null)
                    throw new ArgumentNullException("replacement");
    
                // a little code to grab a cached parsed replacement object
                repl = (RegexReplacement)replref.Get();
    
                if (repl == null || !repl.Pattern.Equals(replacement)) {
                    repl = RegexParser.ParseReplacement(replacement, caps, capsize, capnames, this.roptions);
                    replref.Cache(repl);
                }
    
                return repl.Replace(this, input, count, startat);
            }
    
            /*
             * Static version of simple Replace call
             */
            /// 
            ///    
            ///    Replaces all occurrences of the with the 
            ///     pattern 
            ///    
            /// 
            /// 
            public static String Replace(String input, String pattern, MatchEvaluator evaluator) {
                return new Regex(pattern, RegexOptions.None, true).Replace(input, evaluator);
            }
    
            /*
             * Static version of simple Replace call
             */
            /// 
            ///    
            ///    Replaces all occurrences of the with the recent 
            ///     pattern, starting at the first character
            /// 
            /// 
            public static String Replace(String input, String pattern, MatchEvaluator evaluator, RegexOptions options) {
                return new Regex(pattern, options, true).Replace(input, evaluator);
            }
    
            /*
             * Does the replacement
             */
            /// 
            ///    
            ///    Replaces all occurrences of the with the recent 
            ///     pattern, starting at the first character 
            ///    position
            /// 
            /// 
            public String Replace(String input, MatchEvaluator evaluator) {
                if (input==null)
                    throw new ArgumentNullException("input");
    
                return Replace(input, evaluator, -1, UseOptionR() ? input.Length : 0);
            }
    
            /*
             * Does the replacement
             */
            /// 
            ///    
            ///    Replaces all occurrences of the with the recent 
            ///     pattern, starting at the first character 
            ///    position
            /// 
            /// 
            public String Replace(String input, MatchEvaluator evaluator, int count) {
                if (input==null)
                    throw new ArgumentNullException("input");
    
                return Replace(input, evaluator, count, UseOptionR() ? input.Length : 0);
            }
    
            /*
             * Does the replacement
             */
            /// 
            ///    
            ///    Replaces all occurrences of the (previouly defined) with 
            ///       the recent  pattern, starting at the character
            ///    position 
            /// 
            /// 
            public String Replace(String input, MatchEvaluator evaluator, int count, int startat) {
                if (input==null)
                    throw new ArgumentNullException("input");
    
                return RegexReplacement.Replace(evaluator, this, input, count, startat);
            }
    
            /*
             * Static version of simple Split call
             */
            ///    
            ///       
            ///          Splits the string at the position defined
            ///          by .
            ///       
            ///    
            public static String[] Split(String input, String pattern) {
                return new Regex(pattern, RegexOptions.None, true).Split(input);
            }
    
            /*
             * Static version of simple Split call
             */
            /// 
            ///    
            ///       Splits the string at the position defined by .
            ///    
            /// 
            public static String[] Split(String input, String pattern, RegexOptions options) {
                return new Regex(pattern, options, true).Split(input);
            }
    
            /*
             * Does a split
             */
            /// 
            ///    
            ///       Splits the string at the position defined by
            ///       a previous 
            ///       .
            ///    
            /// 
            public String[] Split(String input) {
                if (input==null)
                    throw new ArgumentNullException("input");
    
                return Split(input, 0, UseOptionR() ? input.Length : 0);
            }
    
            /*
             * Does a split
             */
            /// 
            ///    
            ///       Splits the string at the position defined by a previous
            ///     . 
            ///    
            /// 
            public String[] Split(String input, int count) {
                if (input==null)
                    throw new ArgumentNullException("input");
                
                return RegexReplacement.Split(this, input, count, UseOptionR() ? input.Length : 0);
            }
    
            /*
             * Does a split
             */
            /// 
            ///    
            ///       Splits the string at the position defined by a previous
            ///     . 
            ///    
            /// 
            public String[] Split(String input, int count, int startat) {
                if (input==null)
                    throw new ArgumentNullException("input");
    
                return RegexReplacement.Split(this, input, count, startat);
            }
            
            /// 
            /// 
            [HostProtection(MayLeakOnAbort=true)]
            [ResourceExposure(ResourceScope.Machine)] // The AssemblyName is interesting.
            [ResourceConsumption(ResourceScope.Machine)]
            public static void CompileToAssembly(RegexCompilationInfo[] regexinfos, AssemblyName assemblyname) {
            
                CompileToAssemblyInternal(regexinfos, assemblyname, null, null, Assembly.GetCallingAssembly().Evidence);
            }
    
            /// 
            /// 
            [HostProtection(MayLeakOnAbort=true)]
            [ResourceExposure(ResourceScope.Machine)] // The AssemblyName is interesting.
            [ResourceConsumption(ResourceScope.Machine)]
            public static void CompileToAssembly(RegexCompilationInfo[] regexinfos, AssemblyName assemblyname, CustomAttributeBuilder[] attributes) {
                CompileToAssemblyInternal(regexinfos, assemblyname, attributes, null, Assembly.GetCallingAssembly().Evidence);
            }
    
            [HostProtection(MayLeakOnAbort=true)]
            [ResourceExposure(ResourceScope.Machine)]
            [ResourceConsumption(ResourceScope.Machine)]
            public static void CompileToAssembly(RegexCompilationInfo[] regexinfos, AssemblyName assemblyname, CustomAttributeBuilder[] attributes, String resourceFile) {
                CompileToAssemblyInternal(regexinfos, assemblyname, attributes, resourceFile, Assembly.GetCallingAssembly().Evidence);
            }
    
            [ResourceExposure(ResourceScope.Machine)]  // AssemblyName & resourceFile
            [ResourceConsumption(ResourceScope.Machine)]
            private static void CompileToAssemblyInternal (RegexCompilationInfo[] regexinfos, AssemblyName assemblyname, CustomAttributeBuilder[] attributes, String resourceFile, Evidence evidence) {
                if (assemblyname == null)
                    throw new ArgumentNullException("assemblyname");
    
                if (regexinfos == null)
                    throw new ArgumentNullException("regexinfos");
            
                RegexCompiler.CompileToAssembly(regexinfos, assemblyname, attributes, resourceFile, evidence);
            }
            
            /// 
            /// 
            protected void InitializeReferences() {
                if (refsInitialized)
                    throw new NotSupportedException(SR.GetString(SR.OnlyAllowedOnce));
                
                refsInitialized = true;
                runnerref  = new ExclusiveReference();
                replref    = new SharedReference();
            }
    
            /*
             * Internal worker called by all the public APIs
             */
            internal Match Run(bool quick, int prevlen, String input, int beginning, int length, int startat) {
                Match match;
                RegexRunner runner = null;
    
                if (startat < 0 || startat > input.Length)
                    throw new ArgumentOutOfRangeException("start", SR.GetString(SR.BeginIndexNotNegative));
    
                if (length < 0 || length > input.Length)
                    throw new ArgumentOutOfRangeException("length", SR.GetString(SR.LengthNotNegative));
    
                // There may be a cached runner; grab ownership of it if we can.
    
                runner = (RegexRunner)runnerref.Get();
    
                // Create a RegexRunner instance if we need to
    
                if (runner == null) {
                    // Use the compiled RegexRunner factory if the code was compiled to MSIL
    
                    if (factory != null)
                        runner = factory.CreateInstance();
                    else
                        runner = new RegexInterpreter(code, UseOptionInvariant() ? CultureInfo.InvariantCulture : CultureInfo.CurrentCulture);
                }
    
                // Do the scan starting at the requested position
    
                match = runner.Scan(this, input, beginning, beginning + length, startat, prevlen, quick);
    
                // Release or fill the cache slot
    
                runnerref.Release(runner);
    
    #if DBG
                if (Debug && match != null)
                    match.Dump();
    #endif
                return match;
            }
    
            /*
             * Find code cache based on options+pattern
             */
            private static CachedCodeEntry LookupCachedAndUpdate(String key) {
                lock (livecode) {
                    for (LinkedListNode current = livecode.First; current != null; current = current.Next) {
                        if (current.Value._key == key) {
                            // If we find an entry in the cache, move it to the head at the same time. 
                            livecode.Remove(current);
                            livecode.AddFirst(current);
                            return current.Value;
                        }
                    }
                }
    
                return null;
            }
    
            /*
             * Add current code to the cache
             */
            private CachedCodeEntry CacheCode(String key) {
                CachedCodeEntry newcached = null;
    
                lock (livecode) {
                    // first look for it in the cache and move it to the head
                    for (LinkedListNode current = livecode.First; current != null; current = current.Next) {
                        if (current.Value._key == key) {
                            livecode.Remove(current);
                            livecode.AddFirst(current);
                            return current.Value;
                        }
                    }
    
                    // it wasn't in the cache, so we'll add a new one.  Shortcut out for the case where cacheSize is zero.
                    if (cacheSize != 0) {
                        newcached = new CachedCodeEntry(key, capnames, capslist, code, caps, capsize, runnerref, replref);
                        livecode.AddFirst(newcached);
                        if (livecode.Count > cacheSize)
                            livecode.RemoveLast();
                    }
                }
    
                return newcached;
            }
    
            /*
             * True if the O option was set
             */
            /// 
            /// 
            /// 
            protected bool UseOptionC() {
                return(roptions & RegexOptions.Compiled) != 0;
            }
    
            /*
             * True if the L option was set
             */
            /// 
            /// 
            /// 
            protected bool UseOptionR() {
                return(roptions & RegexOptions.RightToLeft) != 0;
            }
    
            internal bool UseOptionInvariant() {
                return(roptions & RegexOptions.CultureInvariant) != 0;
            }
                
    
    #if DBG
            /*
             * True if the regex has debugging enabled
             */
            /// 
            /// 
            /// 
            internal bool Debug {
                get {
                    return(roptions & RegexOptions.Debug) != 0;
                }
            }
    
    #endif
        }
    
    
        /*
         * Callback class
         */
        /// 
        /// 
        [ Serializable() ] 
        public delegate String MatchEvaluator(Match match);
    
    
        /*
         * Used to cache byte codes or compiled factories
         */
        internal sealed class CachedCodeEntry {
            internal string _key;
            internal RegexCode _code;
            internal Hashtable _caps;
            internal Hashtable _capnames;
            internal String[]  _capslist;
            internal int       _capsize;
            internal RegexRunnerFactory _factory;
            internal ExclusiveReference _runnerref;
            internal SharedReference _replref;
    
            internal CachedCodeEntry(string key, Hashtable capnames, String[] capslist, RegexCode code, Hashtable caps, int capsize, ExclusiveReference runner, SharedReference repl) {
    
                _key        = key;
                _capnames   = capnames;
                _capslist   = capslist;
    
                _code       = code;
                _caps       = caps;
                _capsize    = capsize;
    
                _runnerref     = runner;
                _replref       = repl;
            }
    
            internal void AddCompiled(RegexRunnerFactory factory) {
                _factory = factory;
                _code = null;
            }
        }
    
        /*
         * Used to cache one exclusive runner reference
         */
        internal sealed class ExclusiveReference {
            RegexRunner _ref;
            Object _obj;
            int _locked;
    
            /*
             * Return an object and grab an exclusive lock.
             *
             * If the exclusive lock can't be obtained, null is returned;
             * if the object can't be returned, the lock is released.
             *
             */
            internal Object Get() {
                // try to obtain the lock
    
                if (0 == Interlocked.Exchange(ref _locked, 1)) {
                    // grab reference
    
                       
                    Object obj = _ref;
    
                    // release the lock and return null if no reference
    
                    if (obj == null) {
                        _locked = 0;
                        return null;
                    }
    
                    // remember the reference and keep the lock
    
                    _obj = obj;
                    return obj;
                }
    
                return null;
            }
    
            /*
             * Release an object back to the cache
             *
             * If the object is the one that's under lock, the lock
             * is released.
             *
             * If there is no cached object, then the lock is obtained
             * and the object is placed in the cache.
             *
             */
            internal void Release(Object obj) {
                if (obj == null)
                    throw new ArgumentNullException("obj");
    
                // if this reference owns the lock, release it
    
                if (_obj == obj) {
                    _obj = null;
                    _locked = 0;
                    return;
                }
    
                // if no reference owns the lock, try to cache this reference
    
                if (_obj == null) {
                    // try to obtain the lock
    
                    if (0 == Interlocked.Exchange(ref _locked, 1)) {
                        // if there's really no reference, cache this reference
    
                        if (_ref == null)
                            _ref = (RegexRunner) obj;
    
                        // release the lock
    
                        _locked = 0;
                        return;
                    }
                }
            }
        }
    
        /*
         * Used to cache a weak reference in a threadsafe way
         */
        internal sealed class SharedReference {
            WeakReference _ref = new WeakReference(null);
            int _locked;
    
            /*
             * Return an object from a weakref, protected by a lock.
             *
             * If the exclusive lock can't be obtained, null is returned;
             *
             * Note that _ref.Target is referenced only under the protection
             * of the lock. (Is this necessary?)
             */
            internal  Object Get() {
                if (0 == Interlocked.Exchange(ref _locked, 1)) {
                    Object obj = _ref.Target;
                    _locked = 0;
                    return obj;
                }
    
                return null;
            }
    
            /*
             * Suggest an object into a weakref, protected by a lock.
             *
             * Note that _ref.Target is referenced only under the protection
             * of the lock. (Is this necessary?)
             */
            internal void Cache(Object obj) {
                if (0 == Interlocked.Exchange(ref _locked, 1)) {
                    _ref.Target = obj;
                    _locked = 0;
                }
            }
        }
    
    }
    

  • 相关阅读:
    Web前端开发的一点记录
    关于表情符号与UTF-8的探讨
    微信公众号H5游戏本地搭建环境和调试(花生壳+wampserver+微信公众号测试号)
    ES6下的数组去重
    关于JS数组循环删除元素出现下标不对的问题
    好资源收藏
    ftp 操作,支持断点续传或者继续下载。
    推荐 greenrobot eventbus,简化安卓开发,提高安卓维护性,优化安卓性能
    T4模板TextTemplatingFileGenerator和TextTemplatingFilePreprocessor区别
    .net使用FluentValidation进行服务端验证。
  • 原文地址:https://www.cnblogs.com/del/p/1363381.html
Copyright © 2020-2023  润新知