Skip to content

Commit 64c8a96

Browse files
committed
quantifiers updated and created tests for them
1 parent 1c621f9 commit 64c8a96

File tree

6 files changed

+228
-112
lines changed

6 files changed

+228
-112
lines changed

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,15 +53,15 @@ Examples: `->exact("hello world", false, "1+")`
5353
- Write documentation (add credit for https://regexr.com/ and ChatGPT)
5454
- Add automated tests on PR creation or on marging to main branch ✔️
5555

56-
- Make Tests for quantifiers (add grouping)
57-
- Make quantifiers available for special chars
56+
- Make Tests for quantifiers (add grouping) ✔️
57+
- Make quantifiers available for special chars ✔️
5858

5959
##### Coming next
6060

6161
- Implement string resolver pattern to use strings like "text(2)-digits()" (or "text:2-digits", or "text|2-digits") as pattern
6262
- Implement recursive pattern creation (Using "RI-321" string to create pattern matching this string)
6363
- Consider to add Postal Code Pattern
6464
- Make options controllable from config or provider (?)
65-
- Make pattern controllable from config or provider (?)
65+
- Make patterns controllable from config or provider (?)
6666
- I should be able to make new pattern using BuilderPattern
6767
- I should be able to make add custom pattern to the existing one using BuilderPattern

STRUCTURE.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,8 @@ Here you can check the usage structure:
247247
- **?Optional** - Any optional methods like: regex expression flags and `end` method
248248
- **Action** - Final method which performs some action like: `get`, `check`, `toRegex` and etc.
249249

250+
_Note: Action methods have replicas in `BuilderPattern` to ensure that `end` method remains optional_
251+
250252
# Conclusion
251253

252254
EloquentRegex simplifies the creation and execution of regular expressions in Laravel applications. Through its intuitive API, developers can quickly implement complex regex operations with precision and flexibility. Whether utilizing ready-to-use patterns for common tasks or crafting custom solutions with dynamic options, EloquentRegex enhances productivity and code clarity.

src/Patterns/BuilderPattern.php

Lines changed: 49 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -87,19 +87,38 @@ public function getMatchesValidationPattern(): string {
8787
* @param string|null $quantifier The quantifier to apply. Can be 'zeroOrMore', 'oneOrMore', or 'optional'.
8888
* @return string The modified pattern with the quantifier applied.
8989
*/
90-
private function applyQuantifier(string $pattern, string|null $quantifier): string {
91-
switch ($quantifier) {
92-
case 'zeroOrMore' || '0>' || '0+':
93-
$p = $pattern . '*';
94-
return $this->lazy ? $this->addLazy($p) : $p;
95-
case 'oneOrMore' || '1>' || '1+':
96-
$p = $pattern . '+';
97-
return $this->lazy ? $this->addLazy($p) : $p;
98-
case 'optional' || '?' || '|':
99-
return $pattern . '?';
100-
default:
101-
return $pattern;
90+
private function applyQuantifier(string $pattern, string|null $q): string {
91+
92+
if (!$q) {
93+
return $pattern;
94+
}
95+
96+
if ($q == 'zeroOrMore' || $q == '0>' || $q == '0+' || $q == '*') {
97+
$p = "(" . $pattern . ')*';
98+
return $this->lazy ? $this->addLazy($p) : $p;
99+
} elseif ($q == 'oneOrMore' || $q == '1>' || $q == '1+' || $q == '+') {
100+
$p = "(" . $pattern . ')+';
101+
return $this->lazy ? $this->addLazy($p) : $p;
102+
} elseif ($q == 'optional' || $q == '?' || $q == '|') {
103+
$p = "(" . $pattern . ')?';
104+
return $this->lazy ? $this->addLazy($p) : $p;
102105
}
106+
107+
if (is_int($q)) {
108+
$p = "(" . $pattern . "){".$q."}";
109+
return $this->lazy ? $this->addLazy($p) : $p;
110+
} elseif (preg_match("/^\d{1,10}$/", $q)) {
111+
$p = "(" . $pattern . '){'.$q.'}';
112+
return $this->lazy ? $this->addLazy($p) : $p;
113+
} elseif (preg_match("/^\d{1,10},\d{1,10}$/", $q)) {
114+
$range = explode(",", $q);
115+
$f = $range[0];
116+
$s = $range[1];
117+
$p = "(" . $pattern . ")" . "{" . $f . "," . $s ."}";
118+
return $this->lazy ? $this->addLazy($p) : $p;
119+
}
120+
121+
return $pattern;
103122
}
104123

105124
/**
@@ -111,9 +130,11 @@ private function applyQuantifier(string $pattern, string|null $quantifier): stri
111130
* @return string The generated regex quantifier string.
112131
*/
113132
private function getLengthOption(int|null $length = null, int $minLength = 0, int $maxLength = 0): string {
114-
if (is_int($length) && $length >= 0) {
133+
if (is_int($length) && $length > 0) {
115134
$qntf = "{" . $length . "}";
116135
return $this->lazy ? $this->addLazy($qntf) : $qntf;
136+
} elseif ($length === 0) {
137+
return "";
117138
}
118139

119140
if ($minLength > 0 && $maxLength > 0) {
@@ -159,10 +180,11 @@ public function lazy(): self {
159180
* @param callable $callback A callback that receives a BuilderPattern instance to define the subpattern.
160181
* @return self
161182
*/
162-
public function charSet(callable $callback): self {
183+
public function charSet(callable $callback, ?string $q = null): self {
163184
$subPattern = new self();
164185
$callback($subPattern);
165-
$this->pattern .= '[' . $subPattern->getPattern() . ']';
186+
$p = '[' . $subPattern->getPattern() . ']';
187+
$this->pattern .= $q ? $this->applyQuantifier($p, $q) : $p;
166188
return $this;
167189
}
168190

@@ -172,10 +194,11 @@ public function charSet(callable $callback): self {
172194
* @param callable $callback A callback that receives a BuilderPattern instance to define the subpattern.
173195
* @return self
174196
*/
175-
public function negativeCharSet(callable $callback): self {
197+
public function negativeCharSet(callable $callback, ?string $q = null): self {
176198
$subPattern = new self();
177199
$callback($subPattern);
178-
$this->pattern .= '[^' . $subPattern->getPattern() . ']';
200+
$p = '[^' . $subPattern->getPattern() . ']';
201+
$this->pattern .= $q ? $this->applyQuantifier($p, $q) : $p;
179202
return $this;
180203
}
181204

@@ -185,10 +208,11 @@ public function negativeCharSet(callable $callback): self {
185208
* @param callable $callback A callback that receives a BuilderPattern instance to define the subpattern.
186209
* @return self
187210
*/
188-
public function group(callable $callback): self {
211+
public function group(callable $callback, ?string $q = null): self {
189212
$subPattern = new self();
190213
$callback($subPattern);
191-
$this->pattern .= '(' . $subPattern->getPattern() . ')';
214+
$p = $subPattern->getPattern();
215+
$this->pattern .= $q ? $this->applyQuantifier($p, $q) : '(' . $p . ')';
192216
return $this;
193217
}
194218

@@ -198,10 +222,11 @@ public function group(callable $callback): self {
198222
* @param callable $callback A callback that receives a BuilderPattern instance to define the subpattern.
199223
* @return self
200224
*/
201-
public function nonCapturingGroup(callable $callback): self {
225+
public function nonCapturingGroup(callable $callback, ?string $q = null): self {
202226
$subPattern = new self();
203227
$callback($subPattern);
204-
$this->pattern .= '(?:' . $subPattern->getPattern() . ')';
228+
$p = '(?:' . $subPattern->getPattern() . ')';
229+
$this->pattern .= $q ? $this->applyQuantifier($p, $q) : $p;
205230
return $this;
206231
}
207232

@@ -211,10 +236,11 @@ public function nonCapturingGroup(callable $callback): self {
211236
* @param callable $callback A callback that receives a BuilderPattern instance to define the alternation.
212237
* @return self
213238
*/
214-
public function orPattern(callable $callback): self {
239+
public function orPattern(callable $callback, ?string $q = null): self {
215240
$builder = new self();
216241
$callback($builder);
217-
$this->pattern .= '|' . $builder->getPattern();
242+
$p = $builder->getPattern();
243+
$this->pattern .= $q ? '|' . $this->applyQuantifier($p, $q) : '|' . $p;
218244
return $this;
219245
}
220246

0 commit comments

Comments
 (0)