Exemple #1
0
        public override IScriptable Construct(Context cx, IScriptable scope, object [] args)
        {
            BuiltinRegExp re = new BuiltinRegExp();

            re.compile(cx, scope, args);
            ScriptRuntime.setObjectProtoAndParent(re, scope);
            return(re);
        }
        private static SubString interpretDollar(Context cx, RegExpImpl res, string da, int dp, int [] skip)
        {
            char dc;
            int  num, tmp;

            if (da [dp] != '$')
            {
                Context.CodeBug();
            }

            /* Allow a real backslash (literal "\\") to escape "$1" etc. */
            Context.Versions version = cx.Version;
            if (version != Context.Versions.Default && version <= Context.Versions.JS1_4)
            {
                if (dp > 0 && da [dp - 1] == '\\')
                {
                    return(null);
                }
            }
            int daL = da.Length;

            if (dp + 1 >= daL)
            {
                return(null);
            }
            /* Interpret all Perl match-induced dollar variables. */
            dc = da [dp + 1];
            if (BuiltinRegExp.isDigit(dc))
            {
                int cp;
                if (version != Context.Versions.Default && version <= Context.Versions.JS1_4)
                {
                    if (dc == '0')
                    {
                        return(null);
                    }
                    /* Check for overflow to avoid gobbling arbitrary decimal digits. */
                    num = 0;
                    cp  = dp;
                    while (++cp < daL && BuiltinRegExp.isDigit(dc = da [cp]))
                    {
                        tmp = 10 * num + (dc - '0');
                        if (tmp < num)
                        {
                            break;
                        }
                        num = tmp;
                    }
                }
                else
                {
                    /* ECMA 3, 1-9 or 01-99 */
                    int parenCount = (res.parens == null) ? 0 : res.parens.Length;
                    num = dc - '0';
                    if (num > parenCount)
                    {
                        return(null);
                    }
                    cp = dp + 2;
                    if ((dp + 2) < daL)
                    {
                        dc = da [dp + 2];
                        if (BuiltinRegExp.isDigit(dc))
                        {
                            tmp = 10 * num + (dc - '0');
                            if (tmp <= parenCount)
                            {
                                cp++;
                                num = tmp;
                            }
                        }
                    }
                    if (num == 0)
                    {
                        return(null); /* $0 or $00 is not valid */
                    }
                }
                /* Adjust num from 1 $n-origin to 0 array-index-origin. */
                num--;
                skip [0] = cp - dp;
                return(res.getParenSubString(num));
            }

            skip [0] = 2;
            switch (dc)
            {
            case '$':
                return(new SubString("$"));

            case '&':
                return(res.lastMatch);

            case '+':
                return(res.lastParen);

            case '`':
                if (version == Context.Versions.JS1_2)
                {
                    /*
                     * JS1.2 imitated the Perl4 bug where left context at each step
                     * in an iterative use of a global regexp started from last match,
                     * not from the start of the target string.  But Perl4 does start
                     * $` at the beginning of the target string when it is used in a
                     * substitution, so we emulate that special case here.
                     */
                    res.leftContext.index  = 0;
                    res.leftContext.length = res.lastMatch.index;
                }
                return(res.leftContext);

            case '\'':
                return(res.rightContext);
            }
            return(null);
        }
        public virtual int FindSplit(Context cx, IScriptable scope, string target, string separator, IScriptable reObj, int [] ip, int [] matchlen, bool [] matched, string [] [] parensp)
        {
            int i      = ip [0];
            int length = target.Length;
            int result;

            Context.Versions version = cx.Version;
            BuiltinRegExp    re      = (BuiltinRegExp)reObj;

            while (true)
            {
                // imitating C label
                /* JS1.2 deviated from Perl by never matching at end of string. */
                int ipsave = ip [0]; // reuse ip to save object creation
                ip [0] = i;
                object ret = re.executeRegExp(cx, scope, this, target, ip, BuiltinRegExp.TEST);
                if (ret == null || !ret.Equals(true))
                {
                    // Mismatch: ensure our caller advances i past end of string.
                    ip [0]       = ipsave;
                    matchlen [0] = 1;
                    matched [0]  = false;
                    return(length);
                }
                i           = ip [0];
                ip [0]      = ipsave;
                matched [0] = true;

                SubString sep = this.lastMatch;
                matchlen [0] = sep.length;
                if (matchlen [0] == 0)
                {
                    /*
                     * Empty string match: never split on an empty
                     * match at the start of a find_split cycle.  Same
                     * rule as for an empty global match in
                     * match_or_replace.
                     */
                    if (i == ip [0])
                    {
                        /*
                         * "Bump-along" to avoid sticking at an empty
                         * match, but don't bump past end of string --
                         * our caller must do that by adding
                         * sep->length to our return value.
                         */
                        if (i == length)
                        {
                            if (version == Context.Versions.JS1_2)
                            {
                                matchlen [0] = 1;
                                result       = i;
                            }
                            else
                            {
                                result = -1;
                            }
                            break;
                        }
                        i++;

                        goto again; // imitating C goto
                    }
                }
                // PR_ASSERT((size_t)i >= sep->length);
                result = i - matchlen [0];
                break;


again:
                ;
            }
            int size = (parens == null) ? 0 : parens.Length;

            parensp [0] = new string [size];
            for (int num = 0; num < size; num++)
            {
                SubString parsub = getParenSubString(num);
                parensp [0] [num] = parsub.ToString();
            }
            return(result);
        }
 public virtual object Compile(Context cx, string source, string flags)
 {
     return(BuiltinRegExp.compileRE(source, flags, false));
 }
        /// <summary> Analog of C match_or_replace.</summary>
        private static object matchOrReplace(Context cx, IScriptable scope, IScriptable thisObj, object [] args, RegExpImpl reImpl, GlobData data, bool forceFlat)
        {
            BuiltinRegExp re;

            string str = ScriptConvert.ToString(thisObj);

            data.str = str;
            IScriptable topScope = ScriptableObject.GetTopLevelScope(scope);

            if (args.Length == 0)
            {
                object compiled = BuiltinRegExp.compileRE("", "", false);
                re = new BuiltinRegExp(topScope, compiled);
            }
            else if (args [0] is BuiltinRegExp)
            {
                re = (BuiltinRegExp)args [0];
            }
            else
            {
                string src = ScriptConvert.ToString(args [0]);
                string opt;
                if (data.optarg < args.Length)
                {
                    args [0] = src;
                    opt      = ScriptConvert.ToString(args [data.optarg]);
                }
                else
                {
                    opt = null;
                }
                object compiled = BuiltinRegExp.compileRE(src, opt, forceFlat);
                re = new BuiltinRegExp(topScope, compiled);
            }
            data.regexp = re;

            data.global = (re.Flags & BuiltinRegExp.JSREG_GLOB) != 0;
            int [] indexp = new int [] { 0 };
            object result = null;

            if (data.mode == EcmaScript.NET.RegExpActions.Search)
            {
                result = re.executeRegExp(cx, scope, reImpl, str, indexp, BuiltinRegExp.TEST);
                if (result != null && result.Equals(true))
                {
                    result = (int)reImpl.leftContext.length;
                }
                else
                {
                    result = -1;
                }
            }
            else if (data.global)
            {
                re.lastIndex = 0;
                for (int count = 0; indexp [0] <= str.Length; count++)
                {
                    result = re.executeRegExp(cx, scope, reImpl, str, indexp, BuiltinRegExp.TEST);
                    if (result == null || !result.Equals(true))
                    {
                        break;
                    }
                    if (data.mode == EcmaScript.NET.RegExpActions.Match)
                    {
                        match_glob(data, cx, scope, count, reImpl);
                    }
                    else
                    {
                        if (data.mode != EcmaScript.NET.RegExpActions.Replace)
                        {
                            Context.CodeBug();
                        }
                        SubString lastMatch = reImpl.lastMatch;
                        int       leftIndex = data.leftIndex;
                        int       leftlen   = lastMatch.index - leftIndex;
                        data.leftIndex = lastMatch.index + lastMatch.length;
                        replace_glob(data, cx, scope, reImpl, leftIndex, leftlen);
                    }
                    if (reImpl.lastMatch.length == 0)
                    {
                        if (indexp [0] == str.Length)
                        {
                            break;
                        }
                        indexp [0]++;
                    }
                }
            }
            else
            {
                result = re.executeRegExp(cx, scope, reImpl, str, indexp, ((data.mode == EcmaScript.NET.RegExpActions.Replace) ? BuiltinRegExp.TEST : BuiltinRegExp.MATCH));
            }

            return(result);
        }