Beispiel #1
0
        private bool ParseAssertionType(ExpressionAssertion assertion)
        {
            if (pattern[ptr] == '<')
            {
                switch (pattern[ptr + 1])
                {
                case '=':
                    assertion.Negate = false;
                    break;

                case '!':
                    assertion.Negate = true;
                    break;

                default:
                    return(false);
                }

                assertion.Reverse = true;
                ptr += 2;
            }
            else
            {
                switch (pattern[ptr])
                {
                case '=':
                    assertion.Negate = false;
                    break;

                case '!':
                    assertion.Negate = true;
                    break;

                default:
                    return(false);
                }

                assertion.Reverse = false;
                ptr += 1;
            }

            return(true);
        }
Beispiel #2
0
        private Expression ParseGroupingConstruct(ref RegexOptions options)
        {
            if (pattern[ptr] != '?')
            {
                Group group;

                if (IsExplicitCapture(options))
                {
                    group = new Group();
                }
                else
                {
                    group = new CapturingGroup();
                    caps.Add(group);
                }

                ParseGroup(group, options, null);
                return(group);
            }
            else
            {
                ++ptr;
            }

            switch (pattern[ptr])
            {
            case ':': {                                                         // non-capturing group
                ++ptr;
                Group group = new Group();
                ParseGroup(group, options, null);

                return(group);
            }

            case '>': {                                                         // non-backtracking group
                ++ptr;
                Group group = new NonBacktrackingGroup();
                ParseGroup(group, options, null);

                return(group);
            }

            case 'i':
            case 'm':
            case 'n':
            case 's':
            case 'x':
            case '-': {                                                         // options
                RegexOptions o = options;
                ParseOptions(ref o, false);
                if (pattern[ptr] == '-')
                {
                    ++ptr;
                    ParseOptions(ref o, true);
                }

                if (pattern[ptr] == ':')                                        // pass options to child group
                {
                    ++ptr;
                    Group group = new Group();
                    ParseGroup(group, o, null);
                    return(group);
                }
                else if (pattern[ptr] == ')')                                   // change options of enclosing group
                {
                    ++ptr;
                    options = o;
                    return(null);
                }
                else
                {
                    throw NewParseException("Bad options");
                }
            }

            case '<':
            case '=':
            case '!': {                                                         // lookahead/lookbehind
                ExpressionAssertion asn = new ExpressionAssertion();
                if (!ParseAssertionType(asn))
                {
                    goto case '\'';                                             // it's a (?<name> ) construct
                }
                Group test = new Group();
                ParseGroup(test, options, null);

                asn.TestExpression = test;
                return(asn);
            }

            case '\'': {                                                        // named/balancing group
                char delim;
                if (pattern[ptr] == '<')
                {
                    delim = '>';
                }
                else
                {
                    delim = '\'';
                }

                ++ptr;
                string name = ParseName();

                if (pattern[ptr] == delim)
                {
                    // capturing group

                    if (name == null)
                    {
                        throw NewParseException("Bad group name.");
                    }

                    ++ptr;
                    CapturingGroup cap = new CapturingGroup();
                    cap.Name = name;
                    caps.Add(cap);
                    ParseGroup(cap, options, null);

                    return(cap);
                }
                else if (pattern[ptr] == '-')
                {
                    // balancing group

                    ++ptr;
                    string balance_name = ParseName();
                    if (balance_name == null || pattern[ptr] != delim)
                    {
                        throw NewParseException("Bad balancing group name.");
                    }

                    ++ptr;
                    BalancingGroup bal = new BalancingGroup();
                    bal.Name = name;

                    if (bal.IsNamed)
                    {
                        caps.Add(bal);
                    }

                    refs.Add(bal, balance_name);

                    ParseGroup(bal, options, null);

                    return(bal);
                }
                else
                {
                    throw NewParseException("Bad group name.");
                }
            }

            case '(': {                                                         // expression/capture test
                Assertion asn;

                ++ptr;
                int    p    = ptr;
                string name = ParseName();
                if (name == null || pattern[ptr] != ')')                        // expression test
                // FIXME MS implementation doesn't seem to
                // implement this version of (?(x) ...)

                {
                    ptr = p;
                    ExpressionAssertion expr_asn = new ExpressionAssertion();

                    if (pattern[ptr] == '?')
                    {
                        ++ptr;
                        if (!ParseAssertionType(expr_asn))
                        {
                            throw NewParseException("Bad conditional.");
                        }
                    }
                    else
                    {
                        expr_asn.Negate  = false;
                        expr_asn.Reverse = false;
                    }

                    Group test = new Group();
                    ParseGroup(test, options, null);
                    expr_asn.TestExpression = test;
                    asn = expr_asn;
                }
                else                                                            // capture test
                {
                    ++ptr;
                    asn = new CaptureAssertion(new Literal(name, IsIgnoreCase(options)));
                    refs.Add(asn, name);
                }

                Group group = new Group();
                ParseGroup(group, options, asn);
                return(group);
            }

            case '#': {                                                         // comment
                ++ptr;
                while (pattern[ptr++] != ')')
                {
                    if (ptr >= pattern.Length)
                    {
                        throw NewParseException("Unterminated (?#...) comment.");
                    }
                }
                return(null);
            }

            default:                                                            // error
                throw NewParseException("Bad grouping construct.");
            }
        }