5
5
6
6
namespace Rubberduck . RegexAssistant
7
7
{
8
- public interface Atom : IDescribable
8
+ public interface IAtom : IDescribable
9
9
{
10
10
string Specifier { get ; }
11
11
}
12
12
13
- public class CharacterClass : Atom
13
+ public class CharacterClass : IAtom
14
14
{
15
15
public static readonly string Pattern = @"(?<!\\)\[(?<expression>.*?)(?<!\\)\]" ;
16
16
private static readonly Regex Matcher = new Regex ( "^" + Pattern + "$" ) ;
17
17
18
- public bool InverseMatching { get ; }
19
- public IList < string > CharacterSpecifiers { get ; }
20
- private readonly string specifier ;
18
+ private readonly bool _inverseMatching ;
19
+ public bool InverseMatching { get { return _inverseMatching ; } }
20
+ private readonly IList < string > _characterSpecifiers ;
21
+ public IList < string > CharacterSpecifiers { get { return _characterSpecifiers ; } }
22
+ private readonly string _specifier ;
21
23
22
24
public CharacterClass ( string specifier )
23
25
{
@@ -26,26 +28,25 @@ public CharacterClass(string specifier)
26
28
{
27
29
throw new ArgumentException ( "The given specifier does not denote a character class" ) ;
28
30
}
29
- this . specifier = specifier ;
31
+ this . _specifier = specifier ;
30
32
string actualSpecifier = m . Groups [ "expression" ] . Value ;
31
- InverseMatching = actualSpecifier . StartsWith ( "^" ) ;
32
- CharacterSpecifiers = new List < string > ( ) ;
33
-
34
- ExtractCharacterSpecifiers ( InverseMatching ? actualSpecifier . Substring ( 1 ) : actualSpecifier ) ;
33
+ _inverseMatching = actualSpecifier . StartsWith ( "^" ) ;
34
+ _characterSpecifiers = ExtractCharacterSpecifiers ( InverseMatching ? actualSpecifier . Substring ( 1 ) : actualSpecifier ) ;
35
35
}
36
36
37
37
public string Specifier
38
38
{
39
39
get
40
40
{
41
- return specifier ;
41
+ return _specifier ;
42
42
}
43
43
}
44
44
45
45
private static readonly Regex CharacterRanges = new Regex ( @"(\\[dDwWsS]|(\\[ntfvr]|\\([0-7]{3}|x[\dA-F]{2}|u[\dA-F]{4}|[\\\.\[\]])|.)(-(\\[ntfvr]|\\([0-7]{3}|x[A-F]{2}|u[\dA-F]{4}|[\.\\\[\]])|.))?)" ) ;
46
- private void ExtractCharacterSpecifiers ( string characterClass )
46
+ private IList < string > ExtractCharacterSpecifiers ( string characterClass )
47
47
{
48
48
MatchCollection specifiers = CharacterRanges . Matches ( characterClass ) ;
49
+ var result = new List < string > ( ) ;
49
50
50
51
foreach ( Match specifier in specifiers )
51
52
{
@@ -64,8 +65,9 @@ private void ExtractCharacterSpecifiers(string characterClass)
64
65
continue ;
65
66
}
66
67
}
67
- CharacterSpecifiers . Add ( specifier . Value ) ;
68
+ result . Add ( specifier . Value ) ;
68
69
}
70
+ return result ;
69
71
}
70
72
71
73
public string Description
@@ -84,82 +86,85 @@ private string HumanReadableClass()
84
86
return string . Join ( ", " , CharacterSpecifiers ) ; // join last with and?
85
87
}
86
88
87
- public bool TryMatch ( ref string text )
88
- {
89
- throw new NotImplementedException ( ) ;
90
- }
91
-
92
89
public override bool Equals ( object obj )
93
90
{
94
91
if ( obj is CharacterClass )
95
92
{
96
- return ( obj as CharacterClass ) . specifier . Equals ( specifier ) ;
93
+ return ( obj as CharacterClass ) . _specifier . Equals ( _specifier ) ;
97
94
}
98
95
return false ;
99
96
}
100
97
}
101
98
102
- class Group : Atom
99
+ class Group : IAtom
103
100
{
104
101
public static readonly string Pattern = @"(?<!\\)\((?<expression>.*)(?<!\\)\)" ;
105
102
private static readonly Regex Matcher = new Regex ( "^" + Pattern + "$" ) ;
106
103
107
- private readonly IRegularExpression subexpression ;
108
- private readonly string specifier ;
104
+ private readonly IRegularExpression _subexpression ;
105
+ private readonly string _specifier ;
109
106
110
107
public Group ( string specifier ) {
111
108
Match m = Matcher . Match ( specifier ) ;
112
109
if ( ! m . Success )
113
110
{
114
111
throw new ArgumentException ( "The given specifier does not denote a Group" ) ;
115
112
}
116
- subexpression = RegularExpression . Parse ( m . Groups [ "expression" ] . Value ) ;
117
- this . specifier = specifier ;
113
+ _subexpression = RegularExpression . Parse ( m . Groups [ "expression" ] . Value ) ;
114
+ _specifier = specifier ;
118
115
}
119
116
120
117
public string Specifier
121
118
{
122
119
get
123
120
{
124
- return specifier ;
121
+ return _specifier ;
125
122
}
126
123
}
127
124
128
125
public string Description
129
126
{
130
127
get
131
128
{
132
- return string . Format ( AssistantResources . AtomDescription_Group , specifier ) + "\r \n " + subexpression . Description ;
129
+ return string . Format ( AssistantResources . AtomDescription_Group , _specifier ) + "\r \n " + _subexpression . Description ;
133
130
}
134
131
}
135
132
136
- public bool TryMatch ( ref string text )
137
- {
138
- throw new NotImplementedException ( ) ;
139
- }
140
-
141
133
public override bool Equals ( object obj )
142
134
{
143
135
if ( obj is Group )
144
136
{
145
- return ( obj as Group ) . specifier . Equals ( specifier ) ;
137
+ return ( obj as Group ) . _specifier . Equals ( _specifier ) ;
146
138
}
147
139
return false ;
148
140
}
149
141
}
150
142
151
- class Literal : Atom
143
+ class Literal : IAtom
152
144
{
153
145
public static readonly string Pattern = @"(?<expression>\\(u[\dA-F]{4}|x[\dA-F]{2}|[0-7]{3}|[bB\(\){}\\\[\]\.+*?1-9nftvrdDwWsS])|[^()\[\]{}\\*+?])" ;
154
146
private static readonly Regex Matcher = new Regex ( "^" + Pattern + "$" ) ;
155
147
private static readonly ISet < char > EscapeLiterals = new HashSet < char > ( ) ;
156
- private readonly string specifier ;
148
+ private readonly string _specifier ;
157
149
158
150
static Literal ( ) {
159
151
foreach ( char escape in new char [ ] { '.' , '+' , '*' , '?' , '(' , ')' , '{' , '}' , '[' , ']' , '|' , '\\ ' } )
160
152
{
161
153
EscapeLiterals . Add ( escape ) ;
162
154
}
155
+ _escapeDescriptions . Add ( 'd' , AssistantResources . AtomDescription_Digit ) ;
156
+ _escapeDescriptions . Add ( 'D' , AssistantResources . AtomDescription_NonDigit ) ;
157
+ _escapeDescriptions . Add ( 'b' , AssistantResources . AtomDescription_WordBoundary ) ;
158
+ _escapeDescriptions . Add ( 'B' , AssistantResources . AtomDescription_NonWordBoundary ) ;
159
+ _escapeDescriptions . Add ( 'w' , AssistantResources . AtomDescription_WordCharacter ) ;
160
+ _escapeDescriptions . Add ( 'W' , AssistantResources . AtomDescription_NonWordCharacter ) ;
161
+ _escapeDescriptions . Add ( 's' , AssistantResources . AtomDescription_Whitespace ) ;
162
+ _escapeDescriptions . Add ( 'S' , AssistantResources . AtomDescription_NonWhitespace ) ;
163
+ _escapeDescriptions . Add ( 'n' , AssistantResources . AtomDescription_Newline ) ;
164
+ _escapeDescriptions . Add ( 'r' , AssistantResources . AtomDescription_CarriageReturn ) ;
165
+ _escapeDescriptions . Add ( 'f' , AssistantResources . AtomDescription_FormFeed ) ;
166
+ _escapeDescriptions . Add ( 'v' , AssistantResources . AtomDescription_VTab ) ;
167
+ _escapeDescriptions . Add ( 't' , AssistantResources . AtomDescription_HTab ) ;
163
168
}
164
169
165
170
public Literal ( string specifier )
@@ -169,17 +174,19 @@ public Literal(string specifier)
169
174
{
170
175
throw new ArgumentException ( "The given specifier does not denote a Literal" ) ;
171
176
}
172
- this . specifier = specifier ;
177
+ _specifier = specifier ;
173
178
}
174
179
175
180
public string Specifier
176
181
{
177
182
get
178
183
{
179
- return specifier ;
184
+ return _specifier ;
180
185
}
181
186
}
182
187
188
+
189
+ private static readonly Dictionary < char , string > _escapeDescriptions = new Dictionary < char , string > ( ) ;
183
190
public string Description
184
191
{
185
192
get
@@ -190,9 +197,9 @@ public string Description
190
197
// - escape sequences (each having a different description)
191
198
// - codepoint escapes (belongs into above category but kept separate)
192
199
// - and actually boring literal matches
193
- if ( specifier . Length > 1 )
200
+ if ( _specifier . Length > 1 )
194
201
{
195
- string relevant = specifier . Substring ( 1 ) ; // skip the damn Backslash at the start
202
+ string relevant = _specifier . Substring ( 1 ) ; // skip the damn Backslash at the start
196
203
if ( relevant . Length > 1 ) // longer sequences
197
204
{
198
205
if ( relevant . StartsWith ( "u" ) )
@@ -218,65 +225,23 @@ public string Description
218
225
}
219
226
else
220
227
{
221
- // special escapes here
222
- switch ( relevant [ 0 ] )
223
- {
224
- case 'd' :
225
- return AssistantResources . AtomDescription_Digit ;
226
- case 'D' :
227
- return AssistantResources . AtomDescription_NonDigit ;
228
- case 'b' :
229
- return AssistantResources . AtomDescription_WordBoundary ;
230
- case 'B' :
231
- return AssistantResources . AtomDescription_NonWordBoundary ;
232
- case 'w' :
233
- return AssistantResources . AtomDescription_WordCharacter ;
234
- case 'W' :
235
- return AssistantResources . AtomDescription_NonWordCharacter ;
236
- case 's' :
237
- return AssistantResources . AtomDescription_Whitespace ;
238
- case 'S' :
239
- return AssistantResources . AtomDescription_NonWhitespace ;
240
- case 'n' :
241
- return AssistantResources . AtomDescription_Newline ;
242
- case 'r' :
243
- return AssistantResources . AtomDescription_CarriageReturn ;
244
- case 'f' :
245
- return AssistantResources . AtomDescription_FormFeed ;
246
- case 'v' :
247
- return AssistantResources . AtomDescription_VTab ;
248
- case 't' :
249
- return AssistantResources . AtomDescription_HTab ;
250
- default :
251
- // shouldn't ever happen, so we blow it all up
252
- throw new InvalidOperationException ( "took an escape sequence that shouldn't exist" ) ;
253
- }
228
+ return _escapeDescriptions [ relevant [ 0 ] ] ;
254
229
}
255
230
}
256
- else
231
+ if ( _specifier . Equals ( "." ) )
257
232
{
258
- if ( specifier . Equals ( "." ) )
259
- {
260
- return AssistantResources . AtomDescription_Dot ;
261
- }
262
- // Behaviour with "." needs fix
263
- return string . Format ( AssistantResources . AtomDescription_Literal_ActualLiteral , specifier ) ;
233
+ return AssistantResources . AtomDescription_Dot ;
264
234
}
235
+ return string . Format ( AssistantResources . AtomDescription_Literal_ActualLiteral , _specifier ) ;
265
236
266
- throw new NotImplementedException ( ) ;
267
237
}
268
238
}
269
239
270
- public bool TryMatch ( ref string text )
271
- {
272
- throw new NotImplementedException ( ) ;
273
- }
274
-
275
240
public override bool Equals ( object obj )
276
241
{
277
242
if ( obj is Literal )
278
243
{
279
- return ( obj as Literal ) . specifier . Equals ( specifier ) ;
244
+ return ( obj as Literal ) . _specifier . Equals ( _specifier ) ;
280
245
}
281
246
return false ;
282
247
}
0 commit comments