Exemple #1
0
        private void HandleExplicitNumericGroups(ArrayList explicit_numeric_groups)
        {
            int gid        = gap;
            int i          = 0;
            int n_explicit = explicit_numeric_groups.Count;

            explicit_numeric_groups.Sort();

            // move 'gap' forward to skip over all explicit groups that
            // turn out to match their index
            for (; i < n_explicit; ++i)
            {
                CapturingGroup g = (CapturingGroup)explicit_numeric_groups [i];
                if (g.Index > gid)
                {
                    break;
                }
                if (g.Index == gid)
                {
                    gid++;
                }
            }

            gap = gid;

            // re-index all further groups so that the indexes are contiguous
            int prev = gid;

            for (; i < n_explicit; ++i)
            {
                CapturingGroup g = (CapturingGroup)explicit_numeric_groups [i];
                if (g.Index == prev)
                {
                    g.Index = gid - 1;
                }
                else
                {
                    prev    = g.Index;
                    g.Index = gid++;
                }
            }
        }
Exemple #2
0
        public int GetMapping(Hashtable mapping)
        {
            int end = caps.Count;

            mapping.Add("0", 0);
            for (int i = 0; i < end; i++)
            {
                CapturingGroup group = (CapturingGroup)caps [i];
                string         name  = group.Name != null ? group.Name : group.Index.ToString();
                if (mapping.Contains(name))
                {
                    if ((int)mapping [name] != group.Index)
                    {
                        throw new SystemException("invalid state");
                    }
                    continue;
                }
                mapping.Add(name, group.Index);
            }

            return(gap);
        }
Exemple #3
0
        public int GetMapping(Hashtable mapping)
        {
            int count = caps.Count;

            mapping.Add("0", 0);
            for (int i = 0; i < count; i++)
            {
                CapturingGroup capturingGroup = (CapturingGroup)caps[i];
                string         key            = (capturingGroup.Name == null) ? capturingGroup.Index.ToString() : capturingGroup.Name;
                if (mapping.Contains(key))
                {
                    if ((int)mapping[key] != capturingGroup.Index)
                    {
                        throw new SystemException("invalid state");
                    }
                }
                else
                {
                    mapping.Add(key, capturingGroup.Index);
                }
            }
            return(gap);
        }
Exemple #4
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.");
            }
        }
Exemple #5
0
        private void ResolveReferences()
        {
            int       gid  = 1;
            Hashtable dict = new Hashtable();
            ArrayList explicit_numeric_groups = null;

            // number unnamed groups

            foreach (CapturingGroup group in caps)
            {
                if (group.Name != null)
                {
                    continue;
                }

                dict.Add(gid.ToString(), group);
                group.Index = gid++;
                ++num_groups;
            }

            // number named groups

            foreach (CapturingGroup group in caps)
            {
                if (group.Name == null)
                {
                    continue;
                }

                if (dict.Contains(group.Name))
                {
                    CapturingGroup prev = (CapturingGroup)dict [group.Name];
                    group.Index = prev.Index;

                    if (group.Index == gid)
                    {
                        gid++;
                    }
                    else if (group.Index > gid)
                    {
                        explicit_numeric_groups.Add(group);
                    }
                    continue;
                }

                if (Char.IsDigit(group.Name [0]))
                {
                    int ptr       = 0;
                    int group_gid = ParseDecimal(group.Name, ref ptr);
                    if (ptr == group.Name.Length)
                    {
                        group.Index = group_gid;
                        dict.Add(group.Name, group);
                        ++num_groups;

                        if (group_gid == gid)
                        {
                            gid++;
                        }
                        else
                        {
                            // all numbers before 'gid' are already in the dictionary.  So, we know group_gid > gid
                            if (explicit_numeric_groups == null)
                            {
                                explicit_numeric_groups = new ArrayList(4);
                            }
                            explicit_numeric_groups.Add(group);
                        }

                        continue;
                    }
                }

                string gid_s = gid.ToString();
                while (dict.Contains(gid_s))
                {
                    gid_s = (++gid).ToString();
                }

                dict.Add(gid_s, group);
                dict.Add(group.Name, group);
                group.Index = gid++;
                ++num_groups;
            }

            gap = gid;             // == 1 + num_groups, if explicit_numeric_groups == null

            if (explicit_numeric_groups != null)
            {
                HandleExplicitNumericGroups(explicit_numeric_groups);
            }

            // resolve references

            foreach (Expression expr in refs.Keys)
            {
                string name = (string)refs [expr];
                if (!dict.Contains(name))
                {
                    if (expr is CaptureAssertion && !Char.IsDigit(name [0]))
                    {
                        continue;
                    }
                    BackslashNumber bn = expr as BackslashNumber;
                    if (bn != null && bn.ResolveReference(name, dict))
                    {
                        continue;
                    }
                    throw NewParseException("Reference to undefined group " +
                                            (Char.IsDigit(name[0]) ? "number " : "name ") +
                                            name);
                }

                CapturingGroup group = (CapturingGroup)dict[name];
                if (expr is Reference)
                {
                    ((Reference)expr).CapturingGroup = group;
                }
                else if (expr is CaptureAssertion)
                {
                    ((CaptureAssertion)expr).CapturingGroup = group;
                }
                else if (expr is BalancingGroup)
                {
                    ((BalancingGroup)expr).Balance = group;
                }
            }
        }
Exemple #6
0
        private void ResolveReferences()
        {
            int       gid  = 1;
            Hashtable dict = new Hashtable();

            // number unnamed groups

            foreach (CapturingGroup group in caps)
            {
                if (group.Name == null)
                {
                    dict.Add(gid.ToString(), group);
                    group.Number = gid++;

                    ++num_groups;
                }
            }

            // number named groups

            foreach (CapturingGroup group in caps)
            {
                if (group.Name != null)
                {
                    if (!dict.Contains(group.Name))
                    {
                        dict.Add(group.Name, group);
                        group.Number = gid++;

                        ++num_groups;
                    }
                    else
                    {
                        CapturingGroup prev = (CapturingGroup)dict[group.Name];
                        group.Number = prev.Number;
                    }
                }
            }

            // resolve references

            foreach (Expression expr in refs.Keys)
            {
                string name = (string)refs[expr];
                if (!dict.Contains(name))
                {
                    if (expr is CaptureAssertion && !Char.IsDigit(name [0]))
                    {
                        continue;
                    }
                    throw NewParseException("Reference to undefined group " +
                                            (Char.IsDigit(name[0]) ? "number " : "name ") +
                                            name);
                }

                CapturingGroup group = (CapturingGroup)dict[name];
                if (expr is Reference)
                {
                    ((Reference)expr).CapturingGroup = group;
                }
                else if (expr is CaptureAssertion)
                {
                    ((CaptureAssertion)expr).CapturingGroup = group;
                }
                else if (expr is BalancingGroup)
                {
                    ((BalancingGroup)expr).Balance = group;
                }
            }
        }
Exemple #7
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.");
			}
		}
Exemple #8
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);
            }
            ptr++;
            switch (pattern[ptr])
            {
            case ':':
            {
                ptr++;
                Group group6 = new Group();
                ParseGroup(group6, options, null);
                return(group6);
            }

            case '>':
            {
                ptr++;
                Group group2 = new NonBacktrackingGroup();
                ParseGroup(group2, options, null);
                return(group2);
            }

            case '-':
            case 'i':
            case 'm':
            case 'n':
            case 's':
            case 'x':
            {
                RegexOptions options2 = options;
                ParseOptions(ref options2, negate: false);
                if (pattern[ptr] == '-')
                {
                    ptr++;
                    ParseOptions(ref options2, negate: true);
                }
                if (pattern[ptr] == ':')
                {
                    ptr++;
                    Group group3 = new Group();
                    ParseGroup(group3, options2, null);
                    return(group3);
                }
                if (pattern[ptr] == ')')
                {
                    ptr++;
                    options = options2;
                    return(null);
                }
                throw NewParseException("Bad options");
            }

            case '!':
            case '<':
            case '=':
            {
                ExpressionAssertion expressionAssertion2 = new ExpressionAssertion();
                if (!ParseAssertionType(expressionAssertion2))
                {
                    goto case '\'';
                }
                Group group7 = new Group();
                ParseGroup(group7, options, null);
                expressionAssertion2.TestExpression = group7;
                return(expressionAssertion2);
            }

            case '\'':
            {
                char c = (pattern[ptr] != '<') ? '\'' : '>';
                ptr++;
                string text2 = ParseName();
                if (pattern[ptr] == c)
                {
                    if (text2 == null)
                    {
                        throw NewParseException("Bad group name.");
                    }
                    ptr++;
                    CapturingGroup capturingGroup = new CapturingGroup();
                    capturingGroup.Name = text2;
                    caps.Add(capturingGroup);
                    ParseGroup(capturingGroup, options, null);
                    return(capturingGroup);
                }
                if (pattern[ptr] == '-')
                {
                    ptr++;
                    string text3 = ParseName();
                    if (text3 == null || pattern[ptr] != c)
                    {
                        throw NewParseException("Bad balancing group name.");
                    }
                    ptr++;
                    BalancingGroup balancingGroup = new BalancingGroup();
                    balancingGroup.Name = text2;
                    if (balancingGroup.IsNamed)
                    {
                        caps.Add(balancingGroup);
                    }
                    refs.Add(balancingGroup, text3);
                    ParseGroup(balancingGroup, options, null);
                    return(balancingGroup);
                }
                throw NewParseException("Bad group name.");
            }

            case '(':
            {
                ptr++;
                int       num  = ptr;
                string    text = ParseName();
                Assertion assertion;
                if (text == null || pattern[ptr] != ')')
                {
                    ptr = num;
                    ExpressionAssertion expressionAssertion = new ExpressionAssertion();
                    if (pattern[ptr] == '?')
                    {
                        ptr++;
                        if (!ParseAssertionType(expressionAssertion))
                        {
                            throw NewParseException("Bad conditional.");
                        }
                    }
                    else
                    {
                        expressionAssertion.Negate  = false;
                        expressionAssertion.Reverse = false;
                    }
                    Group group4 = new Group();
                    ParseGroup(group4, options, null);
                    expressionAssertion.TestExpression = group4;
                    assertion = expressionAssertion;
                }
                else
                {
                    ptr++;
                    assertion = new CaptureAssertion(new Literal(text, IsIgnoreCase(options)));
                    refs.Add(assertion, text);
                }
                Group group5 = new Group();
                ParseGroup(group5, options, assertion);
                return(group5);
            }

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

            default:
                throw NewParseException("Bad grouping construct.");
            }
        }
Exemple #9
0
        private void ResolveReferences()
        {
            int       num       = 1;
            Hashtable hashtable = new Hashtable();
            ArrayList arrayList = null;

            foreach (CapturingGroup cap in caps)
            {
                if (cap.Name == null)
                {
                    hashtable.Add(num.ToString(), cap);
                    cap.Index = num++;
                    num_groups++;
                }
            }
            foreach (CapturingGroup cap2 in caps)
            {
                if (cap2.Name != null)
                {
                    if (hashtable.Contains(cap2.Name))
                    {
                        CapturingGroup capturingGroup3 = (CapturingGroup)hashtable[cap2.Name];
                        cap2.Index = capturingGroup3.Index;
                        if (cap2.Index == num)
                        {
                            num++;
                        }
                        else if (cap2.Index > num)
                        {
                            arrayList.Add(cap2);
                        }
                    }
                    else
                    {
                        if (char.IsDigit(cap2.Name[0]))
                        {
                            int num3 = 0;
                            int num4 = ParseDecimal(cap2.Name, ref num3);
                            if (num3 == cap2.Name.Length)
                            {
                                cap2.Index = num4;
                                hashtable.Add(cap2.Name, cap2);
                                num_groups++;
                                if (num4 == num)
                                {
                                    num++;
                                }
                                else
                                {
                                    if (arrayList == null)
                                    {
                                        arrayList = new ArrayList(4);
                                    }
                                    arrayList.Add(cap2);
                                }
                                continue;
                            }
                        }
                        string key = num.ToString();
                        while (hashtable.Contains(key))
                        {
                            int num5 = ++num;
                            key = num5.ToString();
                        }
                        hashtable.Add(key, cap2);
                        hashtable.Add(cap2.Name, cap2);
                        cap2.Index = num++;
                        num_groups++;
                    }
                }
            }
            gap = num;
            if (arrayList != null)
            {
                HandleExplicitNumericGroups(arrayList);
            }
            foreach (Expression key2 in refs.Keys)
            {
                string text = (string)refs[key2];
                if (!hashtable.Contains(text))
                {
                    if (!(key2 is CaptureAssertion) || char.IsDigit(text[0]))
                    {
                        BackslashNumber backslashNumber = key2 as BackslashNumber;
                        if (backslashNumber == null || !backslashNumber.ResolveReference(text, hashtable))
                        {
                            throw NewParseException("Reference to undefined group " + ((!char.IsDigit(text[0])) ? "name " : "number ") + text);
                        }
                    }
                }
                else
                {
                    CapturingGroup capturingGroup4 = (CapturingGroup)hashtable[text];
                    if (key2 is Reference)
                    {
                        ((Reference)key2).CapturingGroup = capturingGroup4;
                    }
                    else if (key2 is CaptureAssertion)
                    {
                        ((CaptureAssertion)key2).CapturingGroup = capturingGroup4;
                    }
                    else if (key2 is BalancingGroup)
                    {
                        ((BalancingGroup)key2).Balance = capturingGroup4;
                    }
                }
            }
        }
Exemple #10
0
 public BalancingGroup()
 {
     this.balance = null;
 }