|
@@ -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; }
|