11<?php
22
3+ declare (strict_types=1 );
4+
5+ /*
6+ * Copyright 2025 Shaun Simmons
7+ *
8+ * For the full copyright and license information, please view the LICENSE
9+ * file that was distributed with this source code.
10+ *
11+ * Based on rrule.js text parsing functionality
12+ * Copyright 2010, Jakub Roztocil and Lars Schoning
13+ * https://github.com/jkbr/rrule/blob/master/LICENCE
14+ */
15+
316namespace Recurr ;
417
518use Recurr \Exception \InvalidArgument ;
619
720/**
8- * TextParser - Parses natural language text into Rule options
9- *
10- * Based on the rrule.js text parsing functionality
21+ * Parses natural language text into Rule options.
22+ *
23+ * Based on the rrule.js text parsing functionality.
1124 * Supports phrases like:
1225 * - "every day"
13- * - "every 2 weeks"
26+ * - "every 2 weeks"
1427 * - "every day for 3 times"
1528 * - "every Monday"
1629 * - "every month on the 15th"
30+ *
31+ * @author Fabiano Lothor <[email protected] > 1732 */
1833class TextParser
1934{
@@ -44,9 +59,10 @@ public function __construct()
4459 }
4560
4661 /**
47- * Parse natural language text into Rule options array
48- *
62+ * Parse natural language text into Rule options array.
63+ *
4964 * @param string $text Natural language text describing recurrence
65+ *
5066 * @return array<string, mixed>|null Options array suitable for Rule constructor
5167 */
5268 public function parseText (string $ text ): ?array
@@ -69,6 +85,9 @@ public function parseText(string $text): ?array
6985 }
7086 }
7187
88+ /**
89+ * Initialize the token patterns for text parsing.
90+ */
7291 private function initializeTokens (): void
7392 {
7493 $ this ->tokens = [
@@ -115,6 +134,11 @@ private function initializeTokens(): void
115134 ];
116135 }
117136
137+ /**
138+ * Move to the next symbol in the text.
139+ *
140+ * @return bool True if a symbol was found, false if parsing is complete
141+ */
118142 private function nextSymbol (): bool
119143 {
120144 $ this ->symbol = null ;
@@ -158,8 +182,11 @@ private function nextSymbol(): bool
158182 }
159183
160184 /**
161- * @param string $name
162- * @return array<string>|false
185+ * Accept a specific symbol if it matches the current symbol.
186+ *
187+ * @param string $name Symbol name to match
188+ *
189+ * @return array<string>|false Matched symbol data or false if no match
163190 */
164191 private function accept (string $ name ): array |false
165192 {
@@ -172,8 +199,13 @@ private function accept(string $name): array|false
172199 }
173200
174201 /**
175- * @param string $name
176- * @return bool
202+ * Expect a specific symbol and throw exception if not found.
203+ *
204+ * @param string $name Symbol name to expect
205+ *
206+ * @return bool Always returns true if symbol is found
207+ *
208+ * @throws InvalidArgument If expected symbol is not found
177209 */
178210 private function expect (string $ name ): bool
179211 {
@@ -184,18 +216,32 @@ private function expect(string $name): bool
184216 }
185217
186218 /**
187- * @return array<string>|false
219+ * Accept a number symbol.
220+ *
221+ * @return array<string>|false Number data or false if current symbol is not a number
188222 */
189223 private function acceptNumber (): array |false
190224 {
191225 return $ this ->accept ('number ' );
192226 }
193227
228+ /**
229+ * Check if parsing is complete.
230+ *
231+ * @return bool True if parsing is done
232+ */
194233 private function isDone (): bool
195234 {
196235 return $ this ->done && $ this ->symbol === null ;
197236 }
198237
238+ /**
239+ * Parse a complete recurrence statement.
240+ *
241+ * Handles patterns like "every [n] frequency [for count times]".
242+ *
243+ * @throws InvalidArgument If statement cannot be parsed
244+ */
199245 private function parseStatement (): void
200246 {
201247 // every [n]
0 commit comments