|
9 | 9 | use Phplrt\Contracts\Lexer\TokenInterface; |
10 | 10 | use Phplrt\Contracts\Parser\ParserRuntimeExceptionInterface; |
11 | 11 | use Phplrt\Contracts\Source\ReadableInterface; |
| 12 | +use Phplrt\Contracts\Source\SourceExceptionInterface; |
12 | 13 | use Phplrt\Contracts\Source\SourceFactoryInterface; |
13 | 14 | use Phplrt\Lexer\Config\PassthroughHandler; |
14 | 15 | use Phplrt\Lexer\Lexer; |
|
20 | 21 | use Phplrt\Parser\Parser as ParserCombinator; |
21 | 22 | use Phplrt\Parser\ParserConfigsInterface; |
22 | 23 | use Phplrt\Source\SourceFactory; |
23 | | -use TypeLang\Parser\Exception\SemanticException; |
24 | 24 | use TypeLang\Parser\Exception\ParseException; |
| 25 | +use TypeLang\Parser\Exception\SemanticException; |
25 | 26 | use TypeLang\Parser\Node\Literal\IntLiteralNode; |
26 | 27 | use TypeLang\Parser\Node\Literal\StringLiteralNode; |
27 | 28 | use TypeLang\Parser\Node\Stmt\TypeStatement; |
@@ -125,83 +126,109 @@ public function parse(#[Language('PHP')] mixed $source): ?TypeStatement |
125 | 126 | { |
126 | 127 | $this->lastProcessedTokenOffset = 0; |
127 | 128 |
|
128 | | - /** @psalm-suppress PossiblyInvalidArgument */ |
129 | | - $source = $this->sources->create($source); |
130 | | - |
131 | 129 | try { |
| 130 | + $instance = $this->sources->create($source); |
132 | 131 |
|
133 | | - foreach ($this->parser->parse($source) as $stmt) { |
134 | | - if ($stmt instanceof TypeStatement) { |
135 | | - $context = $this->parser->getLastExecutionContext(); |
| 132 | + try { |
| 133 | + foreach ($this->parser->parse($instance) as $stmt) { |
| 134 | + if ($stmt instanceof TypeStatement) { |
| 135 | + $context = $this->parser->getLastExecutionContext(); |
136 | 136 |
|
137 | | - if ($context !== null) { |
138 | | - $token = $context->buffer->current(); |
| 137 | + if ($context !== null) { |
| 138 | + $token = $context->buffer->current(); |
139 | 139 |
|
140 | | - $this->lastProcessedTokenOffset = $token->getOffset(); |
141 | | - } |
| 140 | + $this->lastProcessedTokenOffset = $token->getOffset(); |
| 141 | + } |
142 | 142 |
|
143 | | - return $stmt; |
| 143 | + return $stmt; |
| 144 | + } |
144 | 145 | } |
145 | | - } |
146 | 146 |
|
147 | | - return null; |
148 | | - } catch (UnexpectedTokenException $e) { |
149 | | - throw $this->unexpectedTokenError($e, $source); |
150 | | - } catch (UnrecognizedTokenException $e) { |
151 | | - throw $this->unrecognizedTokenError($e, $source); |
152 | | - } catch (ParserRuntimeExceptionInterface $e) { |
153 | | - throw $this->parserRuntimeError($e, $source); |
154 | | - } catch (SemanticException $e) { |
155 | | - throw $this->semanticError($e, $source); |
156 | | - } catch (\Throwable $e) { |
157 | | - throw $this->internalError($e, $source); |
| 147 | + return null; |
| 148 | + } catch (UnexpectedTokenException $e) { |
| 149 | + throw $this->unexpectedTokenError($e, $instance); |
| 150 | + } catch (UnrecognizedTokenException $e) { |
| 151 | + throw $this->unrecognizedTokenError($e, $instance); |
| 152 | + } catch (ParserRuntimeExceptionInterface $e) { |
| 153 | + throw $this->parserRuntimeError($e, $instance); |
| 154 | + } catch (SemanticException $e) { |
| 155 | + throw $this->semanticError($e, $instance); |
| 156 | + } catch (\Throwable $e) { |
| 157 | + throw $this->internalError($e, $instance); |
| 158 | + } |
| 159 | + } catch (SourceExceptionInterface $e) { |
| 160 | + throw new ParseException( |
| 161 | + message: $e->getMessage(), |
| 162 | + code: ParseException::ERROR_CODE_INTERNAL_ERROR, |
| 163 | + previous: $e, |
| 164 | + ); |
158 | 165 | } |
| 166 | + |
| 167 | + return null; |
159 | 168 | } |
160 | 169 |
|
| 170 | + /** |
| 171 | + * @throws SourceExceptionInterface In case of source content reading error. |
| 172 | + */ |
161 | 173 | private function unexpectedTokenError(UnexpectedTokenException $e, ReadableInterface $source): ParseException |
162 | 174 | { |
163 | 175 | $token = $e->getToken(); |
164 | 176 |
|
165 | 177 | return ParseException::fromUnexpectedToken( |
166 | | - $token->getValue(), |
167 | | - $source->getContents(), |
168 | | - $token->getOffset(), |
| 178 | + char: $token->getValue(), |
| 179 | + statement: $source->getContents(), |
| 180 | + offset: $token->getOffset(), |
169 | 181 | ); |
170 | 182 | } |
171 | 183 |
|
| 184 | + /** |
| 185 | + * @throws SourceExceptionInterface In case of source content reading error. |
| 186 | + */ |
172 | 187 | private function unrecognizedTokenError(UnrecognizedTokenException $e, ReadableInterface $source): ParseException |
173 | 188 | { |
174 | 189 | $token = $e->getToken(); |
175 | 190 |
|
176 | 191 | return ParseException::fromUnrecognizedToken( |
177 | | - $token->getValue(), |
178 | | - $source->getContents(), |
179 | | - $token->getOffset(), |
| 192 | + token: $token->getValue(), |
| 193 | + statement: $source->getContents(), |
| 194 | + offset: $token->getOffset(), |
180 | 195 | ); |
181 | 196 | } |
182 | 197 |
|
| 198 | + /** |
| 199 | + * @throws SourceExceptionInterface In case of source content reading error. |
| 200 | + */ |
183 | 201 | private function semanticError(SemanticException $e, ReadableInterface $source): ParseException |
184 | 202 | { |
185 | 203 | return ParseException::fromSemanticError( |
186 | | - $e->getMessage(), |
187 | | - $source->getContents(), |
188 | | - $e->getOffset(), |
189 | | - $e->getCode(), |
| 204 | + message: $e->getMessage(), |
| 205 | + statement: $source->getContents(), |
| 206 | + offset: $e->getOffset(), |
| 207 | + code: $e->getCode(), |
190 | 208 | ); |
191 | 209 | } |
192 | 210 |
|
| 211 | + /** |
| 212 | + * @throws SourceExceptionInterface In case of source content reading error. |
| 213 | + */ |
193 | 214 | private function parserRuntimeError(ParserRuntimeExceptionInterface $e, ReadableInterface $source): ParseException |
194 | 215 | { |
195 | 216 | $token = $e->getToken(); |
196 | 217 |
|
197 | 218 | return ParseException::fromUnrecognizedSyntaxError( |
198 | | - $source->getContents(), |
199 | | - $token->getOffset(), |
| 219 | + statement: $source->getContents(), |
| 220 | + offset: $token->getOffset(), |
200 | 221 | ); |
201 | 222 | } |
202 | 223 |
|
| 224 | + /** |
| 225 | + * @throws SourceExceptionInterface In case of source content reading error. |
| 226 | + */ |
203 | 227 | private function internalError(\Throwable $e, ReadableInterface $source): ParseException |
204 | 228 | { |
205 | | - return ParseException::fromInternalError($source->getContents(), $e); |
| 229 | + return ParseException::fromInternalError( |
| 230 | + statement: $source->getContents(), |
| 231 | + e: $e |
| 232 | + ); |
206 | 233 | } |
207 | 234 | } |
0 commit comments