2 // NamingGroupsConstruct.jvm.cs
5 // Arina Itkes <arinai@mainsoft.com>
7 // Copyright (C) 2007 Mainsoft, Inc.
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33 using System.Collections;
34 using System.Collections.Generic;
36 using java.util.regex;
39 namespace System.Text.RegularExpressions
41 sealed class NamingGroupsConstruct : IConstructType
43 private const string NAMED_GROUP_PATTERN_1 = @"\(\?<[A-Za-z]\w*>.*\)";
44 private const string NAMED_GROUP_PATTERN_2 = @"\(\?'[A-Za-z]\w*'.*\)";
45 private const string NUMBERED_GROUP_PATTERN_1 = @"\(\?<\d+>.*\)";
46 private const string NUMBERED_GROUP_PATTERN_2 = @"\(\?'\d+'.*\)";
47 private const string LEFT_PAREN = @"\(";
48 private const string ESCAPED_LEFT_PAREN_TEMPL = @"(?<=(?:[^\\]|\A)(?:[\\]{2}){0,1073741823})\\\(";
49 private const string NON_CAPTURED_GROUP_PATTERN = @"(?:^\?[:imnsx=!>-]|^\?<[!=])";
50 private const string NAMED_GROUP_PATTERN1 = @"^\?<([A-Za-z]\w*)>";
51 private const string NAMED_GROUP_PATTERN2 = @"^\?'([A-Za-z]\w*)'";
52 private const string NUMBERED_GROUP_PATTERN1 = @"^\?<(\d+)>";
53 private const string NUMBERED_GROUP_PATTERN2 = @"^\?'(\d+)'";
54 private const string QUESTION = "?";
55 private const string REMOVED_NAME_PATTERN_TEMPL1 = @"(?<=(?:[^\\]|\A)(?:[\\]{2}){0,1073741823}\()\?<[A-Za-z]\w*>";
56 private const string REMOVED_NAME_PATTERN_TEMPL2 = @"(?<=(?:[^\\]|\A)(?:[\\]{2}){0,1073741823}\()\?'[A-Za-z]\w*'";
57 private const string REMOVED_NUMBERED_PATTERN_TEMPL1 = @"(?<=(?:[^\\]|\A)(?:[\\]{2}){0,1073741823}\()\?<\d+>";
58 private const string REMOVED_NUMBERED_PATTERN_TEMPL2 = @"(?<=(?:[^\\]|\A)(?:[\\]{2}){0,1073741823}\()\?'\d+'";
61 public bool HasConstruct (string pattern, RegexOptions options) {
62 if (JavaUtils.IsMatch (pattern, NAMED_GROUP_PATTERN_1)) {
65 if (JavaUtils.IsMatch (pattern, NAMED_GROUP_PATTERN_2)) {
68 if (JavaUtils.IsMatch (pattern, NUMBERED_GROUP_PATTERN_1)) {
71 if (JavaUtils.IsMatch (pattern, NUMBERED_GROUP_PATTERN_2)) {
78 public string Reformat (RegexOptions options,
79 string reformattedPattern,
80 PatternGrouping patternGrouping) {
81 if (!HasConstruct (reformattedPattern, options)) {
82 return reformattedPattern;
85 UpdateGroupMapping (reformattedPattern, options, patternGrouping);
87 return ReformatPattern (reformattedPattern);
90 private static string ReformatPattern (string reformattedPattern) {
92 reformattedPattern = JavaUtils.ReplaceAll (reformattedPattern, REMOVED_NAME_PATTERN_TEMPL1, String.Empty);
93 reformattedPattern = JavaUtils.ReplaceAll (reformattedPattern, REMOVED_NAME_PATTERN_TEMPL2, String.Empty);
94 reformattedPattern = JavaUtils.ReplaceAll (reformattedPattern, REMOVED_NUMBERED_PATTERN_TEMPL1, String.Empty);
95 reformattedPattern = JavaUtils.ReplaceAll (reformattedPattern, REMOVED_NUMBERED_PATTERN_TEMPL2, String.Empty);
97 return reformattedPattern;
100 private static void UpdateGroupMapping (string reformattedPattern,
101 RegexOptions options,
102 PatternGrouping patternGrouping) {
104 CharSequence workString = (CharSequence) (object) JavaUtils.ReplaceAll (reformattedPattern, ESCAPED_LEFT_PAREN_TEMPL, String.Empty);
106 //Split pattern by left parenthesis
107 Pattern p = Pattern.compile (LEFT_PAREN);
108 string [] parts = p.split (workString);
110 Pattern nonCapturedGroupPattern = Pattern.compile (NON_CAPTURED_GROUP_PATTERN);
111 Pattern groupNamePattern1 = Pattern.compile (NAMED_GROUP_PATTERN1);
112 Pattern groupNamePattern2 = Pattern.compile (NAMED_GROUP_PATTERN2);
113 Pattern groupNumPattern1 = Pattern.compile (NUMBERED_GROUP_PATTERN1);
114 Pattern groupNumPattern2 = Pattern.compile (NUMBERED_GROUP_PATTERN2);
116 int enoughLength = parts.Length;
117 string [] namedGroups = new string [enoughLength];
118 int [] javaGroupNumberToNetGroupNumber = new int [enoughLength];
119 int capturedGroupsCount = 0;
120 int namedGroupsCount = 0;
121 int nonamedGroupsCount = 0;
122 int sameGroupsCounter = 0;
125 for (int i = 1; i < parts.Length; ++i) {
127 if (parts [i].StartsWith (QUESTION) == false) {
128 javaGroupNumberToNetGroupNumber [++capturedGroupsCount] = ++nonamedGroupsCount;
132 //Skip non captured groups
133 Matcher partMatcher =
134 nonCapturedGroupPattern.matcher ((CharSequence) (object) parts [i]);
135 if (partMatcher.find ()) {
139 //Find named groups by 2 patterns
140 partMatcher = groupNamePattern1.matcher ((CharSequence) (object) parts [i]);
141 if (partMatcher.find ()) {
142 namedGroups [namedGroupsCount++] = partMatcher.group (1);
143 javaGroupNumberToNetGroupNumber [++capturedGroupsCount] = -1;
146 partMatcher = groupNamePattern2.matcher ((CharSequence) (object) parts [i]);
147 if (partMatcher.find ()) {
148 namedGroups [namedGroupsCount++] = partMatcher.group (1);
149 javaGroupNumberToNetGroupNumber [++capturedGroupsCount] = -1;
153 //Find explicitly numbered groups by 2 patterns
154 partMatcher = groupNumPattern1.matcher ((CharSequence) (object) parts [i]);
155 if (partMatcher.find ()) {
156 int netGroupNumber = int.Parse (partMatcher.group (1));
157 if ((options & RegexOptions.ExplicitCapture) == RegexOptions.ExplicitCapture) {
158 namedGroups [namedGroupsCount++] = partMatcher.group (1);
159 javaGroupNumberToNetGroupNumber [++capturedGroupsCount] = -1;
162 javaGroupNumberToNetGroupNumber [++capturedGroupsCount] = netGroupNumber;
163 if (javaGroupNumberToNetGroupNumber [capturedGroupsCount] != netGroupNumber) {
169 partMatcher = groupNumPattern2.matcher ((CharSequence) (object) parts [i]);
170 if (partMatcher.find ()) {
171 int netGroupNumber = int.Parse (partMatcher.group (1));
172 if ((options & RegexOptions.ExplicitCapture) == RegexOptions.ExplicitCapture) {
173 namedGroups [namedGroupsCount++] = partMatcher.group (1);
174 javaGroupNumberToNetGroupNumber [++capturedGroupsCount] = -1;
177 javaGroupNumberToNetGroupNumber [++capturedGroupsCount] = netGroupNumber;
178 if (javaGroupNumberToNetGroupNumber [capturedGroupsCount] != netGroupNumber) {
187 patternGrouping.SetGroups (namedGroups,
188 javaGroupNumberToNetGroupNumber,