예제 #1
0
        /*
        1. Evaluate DecimalEscape to obtain an EscapeValue E.
        2. If E is not a character then go to step 6.
        3. Let ch be E's character.
        4. Let A be a one-element RECharSet containing the character ch.
        5. Call CharacterSetMatcher(A, false) and return its Matcher result.
        6. E must be an integer. Let n be that integer.
        7. If n=0 or n>NCapturingParens then throw a SyntaxError exception.
        8. Return an internal Matcher closure that takes two arguments, a State x
        and a Continuation c, and performs the following:
        1. Let cap be x's captures internal array.
        2. Let s be cap[n].
        3. If s is undefined, then call c(x) and return its result.
        4. Let e be x's endIndex.
        5. Let len be s's length.
        6. Let f be e+len.
        7. If f>InputLength, return failure.
        8. If there exists an integer i between 0 (inclusive) and len (exclusive)
        such that Canonicalize(s[i]) is not the same character as
        Canonicalize(Input [e+i]), then return failure.
        9. Let y be the State (f, cap).
        10. Call c(y) and return its result.
        */
        private static bool backrefMatcher(REGlobalData gData, int parenIndex, char [] chars, int end)
        {
            int len;
            int i;
            int parenContent = gData.parens_index (parenIndex);
            if (parenContent == -1)
                return true;

            len = gData.parens_length (parenIndex);
            if ((gData.cp + len) > end)
                return false;

            if ((gData.regexp.flags & JSREG_FOLD) != 0) {
                for (i = 0; i < len; i++) {
                    if (upcase (chars [parenContent + i]) != upcase (chars [gData.cp + i]))
                        return false;
                }
            }
            else {
                for (i = 0; i < len; i++) {
                    if (chars [parenContent + i] != chars [gData.cp + i])
                        return false;
                }
            }
            gData.cp += len;
            return true;
        }
예제 #2
0
        /*
        * indexp is assumed to be an array of length 1
        */
        internal virtual object executeRegExp(Context cx, IScriptable scopeObj, RegExpImpl res, string str, int [] indexp, int matchType)
        {
            REGlobalData gData = new REGlobalData ();

            int start = indexp [0];
            char [] charArray = str.ToCharArray ();
            int end = charArray.Length;
            if (start > end)
                start = end;
            //
            // Call the recursive matcher to do the real work.
            //
            bool matches = matchRegExp (gData, re, charArray, start, end, res.multiline);
            if (!matches) {
                if (matchType != PREFIX)
                    return null;
                return Undefined.Value;
            }
            int index = gData.cp;
            int i = index;
            indexp [0] = i;
            int matchlen = i - (start + gData.skipped);
            int ep = index;
            index -= matchlen;
            object result;
            IScriptable obj;

            if (matchType == TEST) {
                /*
                * Testing for a match and updating cx.regExpImpl: don't allocate
                * an array object, do return true.
                */
                result = true;
                obj = null;
            }
            else {
                /*
                * The array returned on match has element 0 bound to the matched
                * string, elements 1 through re.parenCount bound to the paren
                * matches, an index property telling the length of the left context,
                * and an input property referring to the input string.
                */
                IScriptable scope = GetTopLevelScope (scopeObj);
                result = ScriptRuntime.NewObject (cx, scope, "Array", null);
                obj = (IScriptable)result;

                string matchstr = new string (charArray, index, matchlen);
                obj.Put (0, obj, matchstr);
            }

            if (re.parenCount == 0) {
                res.parens = null;
                res.lastParen = SubString.EmptySubString;
            }
            else {
                SubString parsub = null;
                int num;
                res.parens = new SubString [re.parenCount];
                for (num = 0; num < re.parenCount; num++) {
                    int cap_index = gData.parens_index (num);
                    string parstr;
                    if (cap_index != -1) {
                        int cap_length = gData.parens_length (num);
                        parsub = new SubString (charArray, cap_index, cap_length);
                        res.parens [num] = parsub;
                        if (matchType == TEST)
                            continue;
                        parstr = parsub.ToString ();
                        obj.Put (num + 1, obj, parstr);
                    }
                    else {
                        if (matchType != TEST)
                            obj.Put (num + 1, obj, Undefined.Value);
                    }
                }
                res.lastParen = parsub;
            }

            if (!(matchType == TEST)) {
                /*
                * Define the index and input properties last for better for/in loop
                * order (so they come after the elements).
                */
                obj.Put ("index", obj, (object)(start + gData.skipped));
                obj.Put ("input", obj, str);
            }

            if (res.lastMatch == null) {
                res.lastMatch = new SubString ();
                res.leftContext = new SubString ();
                res.rightContext = new SubString ();
            }
            res.lastMatch.charArray = charArray;
            res.lastMatch.index = index;
            res.lastMatch.length = matchlen;

            res.leftContext.charArray = charArray;
            if (cx.Version == Context.Versions.JS1_2) {
                /*
                * JS1.2 emulated Perl4.0.1.8 (patch level 36) for global regexps used
                * in scalar contexts, and unintentionally for the string.match "list"
                * psuedo-context.  On "hi there bye", the following would result:
                *
                * Language     while(/ /g){print("$`");}   s/ /$`/g
                * perl4.036    "hi", "there"               "hihitherehi therebye"
                * perl5        "hi", "hi there"            "hihitherehi therebye"
                * js1.2        "hi", "there"               "hihitheretherebye"
                *
                * Insofar as JS1.2 always defined $` as "left context from the last
                * match" for global regexps, it was more consistent than perl4.
                */
                res.leftContext.index = start;
                res.leftContext.length = gData.skipped;
            }
            else {
                /*
                * For JS1.3 and ECMAv2, emulate Perl5 exactly:
                *
                * js1.3        "hi", "hi there"            "hihitherehi therebye"
                */
                res.leftContext.index = 0;
                res.leftContext.length = start + gData.skipped;
            }

            res.rightContext.charArray = charArray;
            res.rightContext.index = ep;
            res.rightContext.length = end - ep;

            return result;
        }