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++; } } }
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); }
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); }
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."); } }
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; } } }
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; } } }
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."); } }
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."); } }
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; } } } }
public BalancingGroup() { this.balance = null; }