The Labs \ Source Viewer \ SSCLI \ Microsoft.JScript \ RegExpConstructor

  1. // ==++==
  2. //
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. //
  14. // ==--==
  15. namespace Microsoft.JScript
  16. {
  17.    
  18.     using System;
  19.     using System.Diagnostics;
  20.     using System.Reflection;
  21.     using System.Text.RegularExpressions;
  22.    
  23.     public sealed class RegExpConstructor : ScriptFunction
  24.     {
  25.         static internal readonly RegExpConstructor ob = new RegExpConstructor();
  26.        
  27.         private RegExpPrototype originalPrototype;
  28.         internal ArrayPrototype arrayPrototype;
  29.         private Regex regex;
  30.         private Match lastRegexMatch;
  31.         internal object inputString;
  32.         private string lastInput;
  33.        
  34.         internal RegExpConstructor() : base(FunctionPrototype.ob, "RegExp", 2)
  35.         {
  36.             this.originalPrototype = RegExpPrototype.ob;
  37.             RegExpPrototype._constructor = this;
  38.             this.proto = RegExpPrototype.ob;
  39.             this.arrayPrototype = ArrayPrototype.ob;
  40.             this.regex = null;
  41.             this.lastRegexMatch = null;
  42.             this.inputString = "";
  43.             this.lastInput = null;
  44.         }
  45.        
  46.         internal RegExpConstructor(LenientFunctionPrototype parent, LenientRegExpPrototype prototypeProp, LenientArrayPrototype arrayPrototype) : base(parent, "RegExp", 2)
  47.         {
  48.             this.originalPrototype = prototypeProp;
  49.             prototypeProp.constructor = this;
  50.             this.proto = prototypeProp;
  51.             this.arrayPrototype = arrayPrototype;
  52.             this.regex = null;
  53.             this.lastRegexMatch = null;
  54.             this.inputString = "";
  55.             this.lastInput = null;
  56.             this.noExpando = false;
  57.         }
  58.        
  59.         internal override object Call(object[] args, object thisob)
  60.         {
  61.             return this.Invoke(args);
  62.         }
  63.        
  64.         internal override object Construct(object[] args)
  65.         {
  66.             return this.CreateInstance(args);
  67.         }
  68.        
  69.         private RegExpObject ConstructNew(object[] args)
  70.         {
  71.             string source = args.Length > 0 && args[0] != null ? Convert.ToString(args[0]) : "";
  72.             if (args.Length > 0 && args[0] is Regex)
  73.                 throw new JScriptException(JSError.TypeMismatch);
  74.             bool ignoreCase = false;
  75.             bool global = false;
  76.             bool multiline = false;
  77.             if (args.Length >= 2 && args[1] != null) {
  78.                 string flags = Convert.ToString(args[1]);
  79.                 for (int i = 0; i < flags.Length; i++) {
  80.                     switch (flags[i]) {
  81.                         case 'i':
  82.                             ignoreCase = true;
  83.                             continue;
  84.                         case 'g':
  85.                             global = true;
  86.                             continue;
  87.                         case 'm':
  88.                             multiline = true;
  89.                             continue;
  90.                     }
  91.                     throw new JScriptException(JSError.RegExpSyntax);
  92.                 }
  93.             }
  94.             return new RegExpObject(this.originalPrototype, source, ignoreCase, global, multiline, this);
  95.         }
  96.        
  97.         public object Construct(string pattern, bool ignoreCase, bool global, bool multiline)
  98.         {
  99.             return new RegExpObject(this.originalPrototype, pattern, ignoreCase, global, multiline, this);
  100.         }
  101.        
  102.         [JSFunctionAttribute(JSFunctionAttributeEnum.HasVarArgs)]
  103.         public new RegExpObject CreateInstance(params object[] args)
  104.         {
  105.             RegExpObject regExpObject;
  106.             if (args == null || args.Length <= 0 || (regExpObject = args[0] as RegExpObject) == null)
  107.                 return ConstructNew(args);
  108.             if (args.Length > 1 && args[1] != null)
  109.                 throw new JScriptException(JSError.RegExpSyntax);
  110.             return new RegExpObject(this.originalPrototype, regExpObject.source, regExpObject.ignoreCase, regExpObject.global, regExpObject.multiline, this);
  111.         }
  112.        
  113.         [JSFunctionAttribute(JSFunctionAttributeEnum.HasVarArgs)]
  114.         public RegExpObject Invoke(params object[] args)
  115.         {
  116.             RegExpObject regExpObject;
  117.             if (args == null || args.Length <= 0 || (regExpObject = args[0] as RegExpObject) == null)
  118.                 return ConstructNew(args);
  119.             if (args.Length > 1 && args[1] != null)
  120.                 throw new JScriptException(JSError.RegExpSyntax);
  121.             return regExpObject;
  122.         }
  123.        
  124.         private object GetIndex()
  125.         {
  126.             return this.lastRegexMatch == null ? -1 : this.lastRegexMatch.Index;
  127.         }
  128.        
  129.         private object GetInput()
  130.         {
  131.             return this.inputString;
  132.         }
  133.        
  134.         private object GetLastIndex()
  135.         {
  136.             return this.lastRegexMatch == null ? -1 : this.lastRegexMatch.Length == 0 ? this.lastRegexMatch.Index + 1 : this.lastRegexMatch.Index + this.lastRegexMatch.Length;
  137.         }
  138.        
  139.         private object GetLastMatch()
  140.         {
  141.             return this.lastRegexMatch == null ? "" : this.lastRegexMatch.ToString();
  142.         }
  143.        
  144.         private object GetLastParen()
  145.         {
  146.             if (this.regex == null || this.lastRegexMatch == null)
  147.                 return "";
  148.             string[] groupNames = this.regex.GetGroupNames();
  149.             if (groupNames.Length <= 1)
  150.                 return "";
  151.             int lastGroupNumber = this.regex.GroupNumberFromName(groupNames[groupNames.Length - 1]);
  152.             Group group = this.lastRegexMatch.Groups[lastGroupNumber];
  153.             return group.Success ? group.ToString() : "";
  154.         }
  155.        
  156.         private object GetLeftContext()
  157.         {
  158.             return this.lastRegexMatch == null || this.lastInput == null ? "" : this.lastInput.Substring(0, this.lastRegexMatch.Index);
  159.         }
  160.        
  161.         internal override object GetMemberValue(string name)
  162.         {
  163.             if (name.Length == 2 && name[0] == '$') {
  164.                 char ch = name[1];
  165.                 switch (ch) {
  166.                     case '1':
  167.                     case '2':
  168.                     case '3':
  169.                     case '4':
  170.                     case '5':
  171.                     case '6':
  172.                     case '7':
  173.                     case '8':
  174.                     case '9':
  175.                        
  176.                         {
  177.                             if (this.lastRegexMatch == null)
  178.                                 return "";
  179.                             Group group = this.lastRegexMatch.Groups[ch.ToString()];
  180.                             return group.Success ? group.ToString() : "";
  181.                         }
  182.                         break;
  183.                     case '`':
  184.                         return this.GetLeftContext();
  185.                     case '\'':
  186.                         return this.GetRightContext();
  187.                     case '&':
  188.                         return this.GetLastMatch();
  189.                     case '+':
  190.                         return this.GetLastParen();
  191.                     case '_':
  192.                         return this.GetInput();
  193.                 }
  194.             }
  195.             return base.GetMemberValue(name);
  196.         }
  197.        
  198.         private object GetRightContext()
  199.         {
  200.             return this.lastRegexMatch == null || this.lastInput == null ? "" : this.lastInput.Substring(this.lastRegexMatch.Index + this.lastRegexMatch.Length);
  201.         }
  202.        
  203.         private void SetInput(object value)
  204.         {
  205.             this.inputString = value;
  206.         }
  207.        
  208.         internal override void SetMemberValue(string name, object value)
  209.         {
  210.             if (this.noExpando)
  211.                 throw new JScriptException(JSError.AssignmentToReadOnly);
  212.             if (name.Length == 2 && name[0] == '$') {
  213.                 switch (name[1]) {
  214.                     case '1':
  215.                     case '2':
  216.                     case '3':
  217.                     case '4':
  218.                     case '5':
  219.                     case '6':
  220.                     case '7':
  221.                     case '8':
  222.                     case '9':
  223.                     case '`':
  224.                     case '\'':
  225.                     case '&':
  226.                     case '+':
  227.                         return;
  228.                     case '_':
  229.                         this.SetInput(value);
  230.                         return;
  231.                 }
  232.             }
  233.             base.SetMemberValue(name, value);
  234.         }
  235.        
  236.         internal int UpdateConstructor(Regex regex, Match match, string input)
  237.         {
  238.             if (!this.noExpando) {
  239.                 this.regex = regex;
  240.                 this.lastRegexMatch = match;
  241.                 this.inputString = input;
  242.                 this.lastInput = input;
  243.             }
  244.             return match.Length == 0 ? match.Index + 1 : match.Index + match.Length;
  245.         }
  246.        
  247.         public object index {
  248.             get { return this.GetIndex(); }
  249.         }
  250.        
  251.         public object input {
  252.             get { return this.GetInput(); }
  253.             set {
  254.                 if (this.noExpando)
  255.                     throw new JScriptException(JSError.AssignmentToReadOnly);
  256.                 this.SetInput(value);
  257.             }
  258.         }
  259.        
  260.         public object lastIndex {
  261.             get { return this.GetLastIndex(); }
  262.         }
  263.        
  264.         public object lastMatch {
  265.             get { return this.GetLastMatch(); }
  266.         }
  267.        
  268.         public object lastParen {
  269.             get { return this.GetLastParen(); }
  270.         }
  271.        
  272.         public object leftContext {
  273.             get { return this.GetLeftContext(); }
  274.         }
  275.        
  276.         public object rightContext {
  277.             get { return this.GetRightContext(); }
  278.         }
  279.     }
  280. }

Developer Fusion