6
6
public class VerbalExpression {
7
7
8
8
private final Pattern pattern ;
9
-
9
+
10
10
public static class Builder {
11
11
12
12
private StringBuilder prefixes = new StringBuilder ();
@@ -15,7 +15,11 @@ public static class Builder {
15
15
private int modifiers = Pattern .MULTILINE ;
16
16
17
17
private String sanitize (final String pValue ) {
18
- return pValue .replaceAll ("[\\ W]" , "\\ \\ $0" );
18
+ return pValue .replaceAll ("[\\ W]" , "\\ \\ $0" );
19
+ }
20
+
21
+ private int countOccurrencesOf (String where , String what ) {
22
+ return (where .length () - where .replace (what , "" ).length ()) / what .length ();
19
23
}
20
24
21
25
public VerbalExpression build () {
@@ -48,7 +52,7 @@ public Builder endOfLine() {
48
52
}
49
53
50
54
public Builder then (String pValue ) {
51
- this .add ("(" + sanitize (pValue ) + ")" );
55
+ this .add ("(?: " + sanitize (pValue ) + ")" );
52
56
return this ;
53
57
}
54
58
@@ -58,32 +62,31 @@ public Builder find(String value) {
58
62
}
59
63
60
64
public Builder maybe (final String pValue ) {
61
- this .add ("(" + sanitize (pValue ) + ")?" );
62
- return this ;
65
+ return this .then (pValue ).add ("?" );
63
66
}
64
67
65
68
public Builder anything () {
66
- this .add ("(.*)" );
69
+ this .add ("(?: .*)" );
67
70
return this ;
68
71
}
69
72
70
73
public Builder anythingButNot (final String pValue ) {
71
- this .add ("([^" + sanitize (pValue ) + "]*)" );
74
+ this .add ("(?: [^" + sanitize (pValue ) + "]*)" );
72
75
return this ;
73
76
}
74
77
75
78
public Builder something () {
76
- this .add ("(.+)" );
79
+ this .add ("(?: .+)" );
77
80
return this ;
78
81
}
79
82
80
83
public Builder somethingButNot (final String pValue ) {
81
- this .add ("([^" + sanitize (pValue ) + "]+)" );
84
+ this .add ("(?: [^" + sanitize (pValue ) + "]+)" );
82
85
return this ;
83
86
}
84
87
85
88
public Builder lineBreak () {
86
- this .add ("(\\ n|(\\ r\\ n))" );
89
+ this .add ("(?: \\ n|(\\ r\\ n))" );
87
90
return this ;
88
91
}
89
92
@@ -115,8 +118,8 @@ public Builder any(final String value) {
115
118
public Builder range (String ... pArgs ) {
116
119
String value = "[" ;
117
120
for (int _to = 1 ; _to < pArgs .length ; _to += 2 ) {
118
- String from = sanitize ((String )pArgs [_to - 1 ]);
119
- String to = sanitize ((String )pArgs [_to ]);
121
+ String from = sanitize ((String ) pArgs [_to - 1 ]);
122
+ String to = sanitize ((String ) pArgs [_to ]);
120
123
121
124
value += from + "-" + to ;
122
125
}
@@ -209,32 +212,82 @@ public Builder searchOneLine(boolean pEnable) {
209
212
}
210
213
211
214
public Builder multiple (final String pValue ) {
212
- String value = this .sanitize (pValue );
213
- switch (value .charAt (0 )) {
215
+ switch (pValue .charAt (0 )) {
214
216
case '*' :
215
217
case '+' :
216
- break ;
218
+ return this . add ( pValue ) ;
217
219
default :
218
- value += '+' ;
220
+ return this . add ( this . sanitize ( pValue ) + '+' ) ;
219
221
}
220
- this .add (value );
222
+ }
223
+
224
+ /**
225
+ * Add count of previous group
226
+ * for example:
227
+ * .find("w").count(3) // produce - (?:w){3}
228
+ *
229
+ * @param count - number of occurrences of previous group in expression
230
+ * @return this Builder
231
+ */
232
+ public Builder count (int count ) {
233
+ this .source .append ("{" ).append (count ).append ("}" );
234
+ return this ;
235
+ }
236
+
237
+ /**
238
+ * Produce range count
239
+ * for example:
240
+ * .find("w").count(1, 3) // produce (?:w){1,3}
241
+ *
242
+ * @param from - minimal number of occurrences
243
+ * @param to - max number of occurrences
244
+ * @return this Builder
245
+ * @see #count(int)
246
+ */
247
+ public Builder count (int from , int to ) {
248
+ this .source .append ("{" ).append (from ).append ("," ).append (to ).append ("}" );
221
249
return this ;
222
250
}
223
251
224
252
public Builder or (final String pValue ) {
225
- if (this .prefixes .indexOf ("(" ) == -1 ) {
226
- this .prefixes .append ("(" );
227
- }
228
- if (this .suffixes .indexOf (")" ) == -1 ) {
229
- this .suffixes .append (")" + this .suffixes .toString ());
253
+ this .prefixes .append ("(" );
254
+
255
+ int opened = countOccurrencesOf (this .prefixes .toString (), "(" );
256
+ int closed = countOccurrencesOf (this .suffixes .toString (), ")" );
257
+
258
+ if (opened >= closed ) {
259
+ this .suffixes = new StringBuilder (")" + this .suffixes .toString ());
230
260
}
231
261
232
- this .add (")|(" );
262
+ this .add (")|(?: " );
233
263
if (pValue != null ) {
234
264
this .then (pValue );
235
265
}
236
266
return this ;
237
267
}
268
+
269
+ /**
270
+ * Adds capture - open brace to current position and closed to suffixes
271
+ * @return this builder
272
+ */
273
+ public Builder capture () {
274
+ this .suffixes .append (")" );
275
+ return this .add ("(" );
276
+ }
277
+
278
+ /**
279
+ * Close brace for previous capture and remove last closed brace from suffixes
280
+ * Can be used to continue build regex after capture or to add multiply captures
281
+ * @return this builder
282
+ */
283
+ public Builder endCapture () {
284
+ if (this .suffixes .length () > 0 && this .suffixes .indexOf (")" ) + 1 == this .suffixes .length ()) {
285
+ this .suffixes .setLength (suffixes .length () - 1 );
286
+ return this .add (")" );
287
+ } else {
288
+ throw new IllegalStateException ("Can't end capture when it not started" );
289
+ }
290
+ }
238
291
}
239
292
240
293
public boolean testExact (final String pToTest ) {
@@ -256,12 +309,16 @@ public boolean test(final String pToTest) {
256
309
private VerbalExpression (final Pattern pattern ) {
257
310
this .pattern = pattern ;
258
311
}
259
-
312
+
260
313
public String getText (String toTest ) {
314
+ return getText (toTest , 0 );
315
+ }
316
+
317
+ public String getText (String toTest , int group ) {
261
318
Matcher m = pattern .matcher (toTest );
262
319
StringBuilder result = new StringBuilder ();
263
- while (m .find ()){
264
- result .append (m .group ());
320
+ while (m .find ()) {
321
+ result .append (m .group (group ));
265
322
}
266
323
return result .toString ();
267
324
}
0 commit comments