Browse Source

Fixing RegExp

Sebastien Ros 8 years ago
parent
commit
fbadc0df5e
1 changed files with 30 additions and 87 deletions
  1. 30 87
      Jint/Native/RegExp/RegExpConstructor.cs

+ 30 - 87
Jint/Native/RegExp/RegExpConstructor.cs

@@ -1,5 +1,6 @@
 using System;
 using System;
 using System.Text.RegularExpressions;
 using System.Text.RegularExpressions;
+using Esprima;
 using Jint.Native.Function;
 using Jint.Native.Function;
 using Jint.Native.Object;
 using Jint.Native.Object;
 using Jint.Runtime;
 using Jint.Runtime;
@@ -18,7 +19,7 @@ namespace Jint.Native.RegExp
             var obj = new RegExpConstructor(engine);
             var obj = new RegExpConstructor(engine);
             obj.Extensible = true;
             obj.Extensible = true;
 
 
-            // The value of the [[Prototype]] internal property of the RegExp constructor is the Function prototype object 
+            // The value of the [[Prototype]] internal property of the RegExp constructor is the Function prototype object
             obj.Prototype = engine.Function.PrototypeObject;
             obj.Prototype = engine.Function.PrototypeObject;
             obj.PrototypeObject = RegExpPrototype.CreatePrototypeObject(engine, obj);
             obj.PrototypeObject = RegExpPrototype.CreatePrototypeObject(engine, obj);
 
 
@@ -81,7 +82,7 @@ namespace Jint.Native.RegExp
                 {
                 {
                     p = TypeConverter.ToString(pattern);
                     p = TypeConverter.ToString(pattern);
                 }
                 }
-                
+
                 f = flags != Undefined.Instance ? TypeConverter.ToString(flags) : "";
                 f = flags != Undefined.Instance ? TypeConverter.ToString(flags) : "";
             }
             }
 
 
@@ -89,7 +90,7 @@ namespace Jint.Native.RegExp
             r.Prototype = PrototypeObject;
             r.Prototype = PrototypeObject;
             r.Extensible = true;
             r.Extensible = true;
 
 
-            var options = ParseOptions(r, f);
+            var options = new Scanner("").ParseRegexOptions(f);
 
 
             try
             try
             {
             {
@@ -102,7 +103,7 @@ namespace Jint.Native.RegExp
 
 
             string s;
             string s;
             s = p;
             s = p;
-             
+
             if (System.String.IsNullOrEmpty(s))
             if (System.String.IsNullOrEmpty(s))
             {
             {
                 s = "(?:)";
                 s = "(?:)";
@@ -125,50 +126,14 @@ namespace Jint.Native.RegExp
             var r = new RegExpInstance(Engine);
             var r = new RegExpInstance(Engine);
             r.Prototype = PrototypeObject;
             r.Prototype = PrototypeObject;
             r.Extensible = true;
             r.Extensible = true;
- 
-            if (regExp[0] != '/')
-            {
-                throw new JavaScriptException(Engine.SyntaxError, "Regexp should start with slash");
-            }
-            var lastSlash = regExp.LastIndexOf('/');
-            // Unescape escaped forward slashes (\/)
-            var pattern = regExp.Substring(1, lastSlash - 1).Replace("\\/", "/");
-            var flags = regExp.Substring(lastSlash + 1);
 
 
-            var options = ParseOptions(r, flags);
-            try
-            {
-                if((RegexOptions.Multiline & options) == RegexOptions.Multiline)
-                {
-                    // Replace all non-escaped $ occurences by \r?$
-                    // c.f. http://programmaticallyspeaking.com/regular-expression-multiline-mode-whats-a-newline.html
-
-                    int index = 0;
-                    var newPattern = pattern;
-                    while((index = newPattern.IndexOf("$", index)) != -1)
-                    {
-                        if(index > 0 && newPattern[index - 1] != '\\')
-                        {
-                            newPattern = newPattern.Substring(0, index) + @"\r?" + newPattern.Substring(index);
-                            index += 4;
-                        }
-                    }
-
-                    r.Value = new Regex(newPattern, options);
-                }
-                else
-                {
-                    r.Value = new Regex(pattern, options);
-                }
-                
-            }
-            catch (Exception e)
-            {
-                throw new JavaScriptException(Engine.SyntaxError, e.Message);
-            }
+            var scanner = new Scanner(regExp);
+            var body = (string)scanner.ScanRegExpBody().Value;
+            var flags = (string)scanner.ScanRegExpFlags().Value;
+            r.Value = scanner.TestRegExp(body, flags, true);
 
 
             r.Flags = flags;
             r.Flags = flags;
-            r.Source = System.String.IsNullOrEmpty(pattern) ? "(?:)" : pattern;
+            r.Source = System.String.IsNullOrEmpty(body) ? "(?:)" : body;
 
 
             r.FastAddProperty("global", r.Global, false, false, false);
             r.FastAddProperty("global", r.Global, false, false, false);
             r.FastAddProperty("ignoreCase", r.IgnoreCase, false, false, false);
             r.FastAddProperty("ignoreCase", r.IgnoreCase, false, false, false);
@@ -179,57 +144,35 @@ namespace Jint.Native.RegExp
             return r;
             return r;
         }
         }
 
 
-        private RegexOptions ParseOptions(RegExpInstance r, string flags)
+        public RegExpInstance Construct(Regex regExp)
         {
         {
-            for (int k = 0; k < flags.Length; k++)
-            {
-                var c = flags[k];
-                if (c == 'g')
-                {
-                    if (r.Global)
-                    {
-                        throw new JavaScriptException(Engine.SyntaxError);
-                    }
-
-                    r.Global = true;
-                }
-                else if (c == 'i')
-                {
-                    if (r.IgnoreCase)
-                    {
-                        throw new JavaScriptException(Engine.SyntaxError);
-                    }
-
-                    r.IgnoreCase = true;
-                }
-                else if (c == 'm')
-                {
-                    if (r.Multiline)
-                    {
-                        throw new JavaScriptException(Engine.SyntaxError);
-                    }
-
-                    r.Multiline = true;
-                }
-                else
-                {
-                    throw new JavaScriptException(Engine.SyntaxError);
-                }
-            }
+            var r = new RegExpInstance(Engine);
+            r.Prototype = PrototypeObject;
+            r.Extensible = true;
 
 
-            var options = RegexOptions.ECMAScript;
+            string flags = "";
 
 
-            if (r.Multiline)
+            if (regExp.Options.HasFlag(RegexOptions.Multiline))
             {
             {
-                options = options | RegexOptions.Multiline;
+                flags += "m";
             }
             }
 
 
-            if (r.IgnoreCase)
+            if (regExp.Options.HasFlag(RegexOptions.IgnoreCase))
             {
             {
-                options = options | RegexOptions.IgnoreCase;
+                flags += "i";
             }
             }
 
 
-            return options;
+            r.Flags = flags;
+            r.Source = regExp.ToString();
+            r.Value = regExp;
+
+            r.FastAddProperty("global", r.Global, false, false, false);
+            r.FastAddProperty("ignoreCase", r.IgnoreCase, false, false, false);
+            r.FastAddProperty("multiline", r.Multiline, false, false, false);
+            r.FastAddProperty("source", r.Source, false, false, false);
+            r.FastAddProperty("lastIndex", 0, true, false, false);
+
+            return r;
         }
         }
 
 
         public RegExpPrototype PrototypeObject { get; private set; }
         public RegExpPrototype PrototypeObject { get; private set; }